次の test.txt ファイルがあります。
var,value
a,1.1234
b,1.7896749
c,2.4982
d,1.2976232
次のコマンドを使用する場合 -
awk -F ',' '{SUM+=$2}END{print SUM}' test.txt
それは印刷する6.7089
ただし、すべての小数点以下の桁数が保存された結果は次のとおりです。6.7088981 この特定の場合だけでなく、通常、結果のすべての小数点以下の桁数を印刷するようにコマンドを作成するにはどうすればよいですか?たとえば、結果に小数点以下10桁がある場合、小数点以下10桁をすべて印刷する必要がありますか?結果に小数点以下5桁しかない場合は、小数点5桁のみを印刷する必要があります。私が使用するオペレーティングシステムはRed Hat Enterprise Linux Server 7.7です。
答え1
OFMT
printf
印刷すると、非整数の数値は(デフォルトでは)書式指定を含む特殊変数を使用して10進文字列表現に変換されます%.6g
。これを変更して、%.17g
IEEE 754二重精度バイナリ浮動小数点数(awk
ほとんどのシステムでほとんどの実装で内部的に使用されている)の最大精度を得ることができます。他の変数(CONVFMT
)は、浮動小数点数が暗黙的に文字列に変換される他の場合(たとえば、数字を他の内容と関連付ける場合)に使用されます。
これらのダブルを使用すると、より高い精度を得ることができず、17以上に上がることは意味がありません。すでに17を使用している場合は、一部の成果物が表示されることがあります。そのような精度が不要な場合は、15個の有効数字がより良い可能性があります。
$ awk -v OFMT=%.17g -F ',' '{SUM+=$2};END{print SUM}' < file
6.7088981000000008
$ awk -v OFMT=%.15g -F ',' '{SUM+=$2};END{print SUM}' < file
6.7088981
印刷されたすべての浮動小数点数に影響しますが、必要な精度で数字を印刷するために直接使用することもOFMT
できます。printf
$ awk -F ',' '{SUM+=$2};END{printf "%.15g\n", SUM}' < file
6.7088981
バージョン4.1.0以降、GNU実装はawk
任意の精度算術サポートを介してコンパイルすることができます(参考文献を参照info gawk 'Arbitrary Precision Arithmetic'
)。システムでこれが発生した場合は、次のこともできます。
gawk -M -v PREC=256 -v OFMT=%.60g -F ',' '{SUM+=$2};END{print SUM}' < file
例:
$ printf 'x,%s\n' 1 1000000000000000000000000000000000.00000000001 |
> gawk -v OFMT=%.15g -F ',' '{SUM+=$2};END{print SUM}'
999999999999999945575230987042816
$ printf 'x,%s\n' 1 1000000000000000000000000000000000.00000000001 |
> gawk -M -v PREC=256 -v OFMT=%.60g -F ',' '{SUM+=$2};END{print SUM}'
1000000000000000000000000000000001.00000000001
ここで別のアプローチは、次を使用することですbc
(数字は常に次のように表現されると仮定します(例ではない0.001
)1e-3
)。
<file tail -n+2 | # skip header
cut -d, -f2 | # extract second field
paste -sd + - | # join input lines with +
bc
次の桁は、.
すべての入力レコードの最大桁になります。
答え2
GNUデータの混合希望の精度で数値を表示するには、デフォルトの出力設定を使用します。
$ datamash --header-in -t, sum 2 < test.txt
6.7088981
OFMT
または、より正確にするには、別のawkを使用してください。
$ awk -F, -v OFMT='%.10g' '{sum += $2} END { print sum }' test.txt
6.7088981
しかし見てください浮動小数点演算に問題がありますか?。浮動小数点数を 10 進法で表示する場合、小数点の後の桁が (ほとんどの) コンピュータで使用される IEEE754、2 進法表現と常に一致するわけではありません。
答え3
すでに議論したように、浮動小数点算術は直感的な答えを得ようとすると問題になりますが、入力できる場合は「」。前に最大3桁しかありません。 9以降は、文字列演算を使用して数値を小数に変換し、それを追加して浮動小数点算術の問題を回避し、印刷する前に結果をFPに変換できます。たとえば、次のようになります。
$ cat tst.awk
BEGIN {
FS = ","
bef = 3
aft = 9
}
NR>1 {
split($2,f,".")
val = sprintf("%*s%-*s",bef,f[1],aft,f[2])
gsub(/ /,0,val)
sum += val
}
END {
sub(".{"aft"}$",".&",sum)
sub(/0+$/,"",sum)
print sum
}
$ awk -f tst.awk file
6.7088981
3および/または9が十分に大きくない場合は、別の数字を選択するか、または2段階の方法を実行して、最初のステップで各数字の最大値を調べます。たとえば、次のようになります。
$ cat tst.awk
BEGIN { FS = "," }
FNR==1 { next }
{ split($2,f,".") }
NR==FNR {
bef = (length(f[1]) > bef ? length(f[1]) : bef)
aft = (length(f[2]) > aft ? length(f[2]) : aft)
next
}
{
val = sprintf("%*s%-*s",bef,f[1],aft,f[2])
gsub(/ /,0,val)
sum += val
}
END {
sub(".{"aft"}$",".&",sum)
sub(/0+$/,"",sum)
print sum
}
$ awk -f tst.awk file file
6.7088981