データ列の最大値を見つけるためにgawkを使用しようとしています。
gawk 'BEGIN{max=0} {if($1>0+max) max=$1} END {print max}' dataset.dat
次のようになりますdataset.dat
。
2.0
2.0e-318
コマンドの出力は次のとおりです。
2.0e-318
当然2より小さい。
私の間違いはどこにありますか?
編集する
興味深いことに、入力ファイルの行を置き換えると、出力は次のようになります。
2.0
編集2
私のgawkバージョンはGNU Awk 4.2.1、API:2.0(GNU MPFR 4.0.2、GNU MP 6.1.2)です。
答え1
2e-318
awkでは、これらの小さな数字()を処理する際にいくつかの問題があります。
まず、入力を使用する前に数値に変換する必要があります。これは通常ゼロを加えることによって行われます。したがって、次のようなものが必要です。
val=0+$1
2. 一般倍精度浮動小数点数(53ビット歌手および11ビット指数)指数の11ビット幅を使用すると、10e-308から10e308の間の数値を表すことができます。したがって、通常の浮動小数点数はこれらの数を表すことはできません。
$ echo '1e-307 1e-308' | awk '{print $1,$1+0,$2,$2+0}' 1e-307 1e-307 1e-308 0
デフォルトでは、GNU awkは次の(一般的な)値を受け入れません
1e-308
。第三に、デフォルト変換フォーマット(CNVFMTとOFMT)
awk
はに設定されます"%.6g"
。有効数字が6個を超える数字は切り捨てられます。もっと重要な番号を確認するように依頼してください。 15と同じです%.15g
(53桁の歌手に17以上を要求しないでください。嘘をつくこともできます)。max
第四に、最初の入力に最初の値を設定することをお勧めします。入力最大値が負の場合、最大値を0に設定すると失敗します。
GNU awkを使用し、任意の精度でコンパイルされている場合は、次のものを使用できます。
$ printf '%s\n' 2e-318 2e-317 2e-307 2e-308 2e-319 |
awk -M -v PREC=100 'BEGIN{OFMT="%.15g"};
{val=0+$1};
NR==1{max=val};
{print($1,val,max)};
val>max{max=val}
END{print max}'
2e-318 2e-318 2e-318
2e-317 2e-317 2e-318
2e-307 2e-307 2e-317
2e-308 2e-308 2e-307
2e-319 2e-319 2e-307
2e-307
または、ユースケースに合わせて簡素化されています。
awk -M -v PREC=100 '
BEGIN{OFMT="%.15g"}; # allow more than 6 figures
{val=0+$1}; # convert input to a (float) number.
NR==1{max=val}; # On the first line, set the max value.
val>max{max=val} # On every entry keep track of the max.
END{print max} # At the end, print the max.
' file # file with input (one per line).
答え2
数値変換を強制するには、各 $1 のプレフィックスで 0+ が必要です。 maxには0+は必要ありません。保存時にすでに数値に変換されています。
Paul--) AWK='
> BEGIN { max = 0; }
> 0+$1 > max { max = 0 + $1; }
> END { print max; }
> '
Paul--) awk "${AWK}" <<[][]
> 2.0
> 2.0e-318
> [][]
2
Paul--) awk "${AWK}" <<[][]
> 2.0e-318
> 2.0
> [][]
2