bashで2つの有効数字を持つ浮動小数点数を印刷したいです(awk、bc、dc、perlなどの一般的なツールを使用することもできます)。
例:
- 76543は76000として印刷する必要があります。
- 0.0076543は0.0076として印刷する必要があります。
どちらの場合も、有効な数字は7と6です。次のような同様の質問に対する回答を読んだ。
ただし、答えは有効数字ではなく、小数点以下の桁数(bc
コマンドscale=2
やprintf
コマンドなど)を制限することに焦点を当てています。%.2f
数値の形式を正確に2桁の有効数字として指定する簡単な方法はありますか?それとも関数を直接書く必要がありますか?
ベストアンサー1
この回答最初の関連質問の最後には、ほぼ破棄された行があります。
%g
指定された有効数字に丸めを参照してください。
だから簡単に書けばいいです
printf "%.2g" "$n"
(ただし、小数点区切り文字とロケールについては、以下のセクションを参照し、Bash以外の場合とprintf
サポートする必要はありません。)%f
%g
例:
$ printf "%.2g\n" 76543 0.0076543
7.7e+04
0.0077
もちろん、純粋な10進数の代わりに歌手指数表現があるので、再変換する必要があります。
$ 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)シェルで書かれていますが、浮動printf
小数点変換を処理していると仮定します。Bashには浮動小数点変換を処理する組み込み関数があるため、printf
ここでは問題ありません。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
小数点区切り記号とロケール設定に関する注意事項
上記のすべてのタスクは次のように仮定します。枢機卿キャラクター(小数点区切り記号とも呼ばれます)は、.
ほとんどの英語ロケールと同様です。他のロケールは逆の方法を使用し、一部のシェルには,
ロケールを尊重する機能が組み込まれています。printf
これらのシェルでは、デフォルトの文字としてLC_NUMERIC=C
強制的に有効にするか、組み込みバージョンを無効にする必要があるかもしれません。後者は(少なくとも一部のバージョンでは)解析引数が常に使用されているように見えますが、印刷は現在のロケールを使用して実行されるという事実によって複雑です。.
/usr/bin/printf
.