Bash

使用 printf 進行奇怪的浮點舍入行為

  • August 24, 2017

我在這個網站上閱讀了一些答案,發現printf四捨五入是可取的。

然而,當我在實踐中使用它時,一個微妙的錯誤導致我出現以下行為:

$ echo 197.5 | xargs printf '%.0f'
198
$ echo 196.5 | xargs printf '%.0f'
196
$ echo 195.5 | xargs printf '%.0f'
196

請注意,舍入196.5變為196

我知道這可能是一些微妙的浮點錯誤(但這不是一個很大的數字,嗯?),所以有人可以對此有所了解嗎?

對此的解決方法也非常受歡迎(因為我現在正在嘗試使用它)。

正如預期的那樣,它是“四捨五入”,或“銀行家四捨五入”。

一個相關的網站答案解釋它。

此類規則試圖解決的問題是(對於帶一位小數的數字),

  • x.1 到 x.4 向下舍入。
  • x.6 到 x.9 向上舍入。

那是4向下和4向上。

為了保持舍入平衡,我們需要捨入 x.5

  • 一次,一次。

這是由規則完成的:«四捨五入到最接近的“偶數”»。

在程式碼中:

LC_NUMERIC=C printf '%.0f ' "$value"

_ echo "$value" | awk 'printf( "%s", $1)'


選項:

總共有四種可能的方法來對數字進行四捨五入:

  1. 已經解釋過的銀行家規則。
  2. 向+無窮大方向舍入。向上取整(對於正數)
  3. 向 -infinite 舍入。向下舍入(對於正數)
  4. 向零舍入。刪除小數(正數或負數)。

向上

如果您確實需要“向上(朝+infinite)”,那麼您可以使用 awk:

value=195.5

公元前 echo "$value" | awk '{ printf("%d", $1 + 0.5) }'

_ echo "scale=0; ($value+0.5)/1" | bc

向下

如果您確實需要“向下舍入(Toward -infinite)”,那麼您可以使用:

value=195.5

公元前 echo "$value" | awk '{ printf("%d", $1 - 0.5) }'

_ echo "scale=0; ($value-0.5)/1" | bc

修剪小數。

刪除小數(點後的任何內容)。

我們也可以直接使用 shell(適用於大多數 shell - 是 POSIX):

value="127.54"    ### Works also for negative numbers.

echo "${value%%.*}"

awk echo "$value"| awk '{printf ("%d",$0)}'

公元前 echo "scale=0; ($value)/1" | bc

引用自:https://unix.stackexchange.com/questions/240112