Bash
如何在bash中用正好2個有效數字格式化浮點數?
我想用 bash 中的兩個有效數字列印浮點數(可能使用 awk、bc、dc、perl 等常用工具)。
例子:
- 76543 應列印為 76000
- 0.0076543 應列印為 0.0076
在這兩種情況下,有效數字都是 7 和 6。我已經閱讀了一些類似問題的答案,例如:
但答案集中在限制小數位數(例如
bc
命令 withscale=2
或printf
command with%.2f
)而不是有效數字。有沒有一種簡單的方法可以用 2 個有效數字格式化數字,還是我必須編寫自己的函式?
這個對第一個連結問題的答案在結尾處幾乎是一次性的:
另請參閱
%g
四捨五入到指定數量的有效數字。所以你可以簡單地寫
printf "%.2g" "$n"
(但請參閱下面關於小數分隔符和語言環境的部分,並註意非 Bash
printf
不需要支持%f
and%g
)。例子:
$ printf "%.2g\n" 76543 0.0076543 7.7e+04 0.0077
當然,您現在有尾數指數表示而不是純十進制,因此您需要轉換回來:
$ printf "%0.f\n" 7.7e+06 7700000 $ printf "%0.7f\n" 7.7e-06 0.0000077
將所有這些放在一起,並將其包裝在一個函式中:
# Function round(precision, number) round() { n=$(printf "%.${1}g" "$2") if [ "$n" != "${n#*e}" ] then f="${n##*e-}" test "$n" = "$f" && f= || f=$(( ${f#0}+$1-1 )) printf "%0.${f}f" "$n" else printf "%s" "$n" fi }
(注意 - 這個函式是用可移植(POSIX)shell 編寫的,但假定它
printf
處理浮點轉換。Bash 有一個內置的printf
,所以你在這裡沒問題,而且 GNU 實現也可以工作,所以大多數 GNU /Linux 系統可以安全地使用 Dash)。測試案例
radix=$(printf %.1f 0) for i in $(seq 12 | sed -e 's/.*/dc -e "12k 1.234 10 & 6 -^*p"/e' -e "y/_._/$radix/") do echo $i "->" $(round 2 $i) done
測試結果
.000012340000 -> 0.000012 .000123400000 -> 0.00012 .001234000000 -> 0.0012 .012340000000 -> 0.012 .123400000000 -> 0.12 1.234 -> 1.2 12.340 -> 12 123.400 -> 120 1234.000 -> 1200 12340.000 -> 12000 123400.000 -> 120000 1234000.000 -> 1200000
關於小數分隔符和語言環境的說明
上面的所有工作都假設基數字元(也稱為小數分隔符)是
.
,就像在大多數英語語言環境中一樣。其他語言環境改為使用,並且一些 shell 具有尊重語言環境,
的內置功能。printf
在這些 shell 中,您可能需要設置LC_NUMERIC=C
強制使用.
as radix 字元,或寫入/usr/bin/printf
以防止使用內置版本。後者由於(至少某些版本)似乎總是使用 解析參數.
,但使用目前語言環境設置列印這一事實而變得複雜。