1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

gawkで整数から微妙にずれた浮動小数点数を配列添字にしたときの挙動

Posted at

ちょっとよくわからない現象にでくわしたのでメモ。

整数から微妙にずれた浮動小数点数というのを作ることがありますね。たとえば 1.0/5.0 を5倍するとか。
どうもそれをawk配列引数にすると変なことが起こります。

調べてみましょう。1より微少量大きな数値を作って、配列添字にして参照できるか試してみます。

aryidx.awk
BEGIN {
  print CONVFMT
  a[1] = 1
  a[2] = 2
  epsilon = 1
  for (i = 0; i <= 60; i++) {
    j = 1 + epsilon
    epsilon *= 0.5
    print "1+2**", -i, "=", j, "<", a[j], ">"
  }
}

実行すると、よくわからないのが次の3点:

  • 浮動小数点数を文字列変換するときに、CONVFMT 組み込み変数(値 "%.6g")を使うはずなのだが、どうも桁数が違う(実際、CONVFMT 変数を書き換えてみても1行目以外出力が変わらない)
  • 配列添字は文字列で、数値を与えた場合には文字列に変換して用いる、とされているのだが、文字列変換結果が "1" なのに配列参照結果が a[1] と同じにならない場合がある
  • おそらく、倍精度浮動小数点数として異なるものは、配列添字として別に扱われるようだ(1+2**-53は倍精度で表現できるが、1+2**-54は1と区別できなくなってしまうため)
$ gawk -f aryidx.awk 
%.6g
1+2** 0 = 2 < 2 >
1+2** -1 = 1.5 <  >
1+2** -2 = 1.25 <  >
1+2** -3 = 1.125 <  >
1+2** -4 = 1.0625 <  >
1+2** -5 = 1.03125 <  >
1+2** -6 = 1.01562 <  >
1+2** -7 = 1.00781 <  >
1+2** -8 = 1.00391 <  >
1+2** -9 = 1.00195 <  >
1+2** -10 = 1.00098 <  >
1+2** -11 = 1.00049 <  >
1+2** -12 = 1.00024 <  >
1+2** -13 = 1.00012 <  >
1+2** -14 = 1.00006 <  >
1+2** -15 = 1.00003 <  >
1+2** -16 = 1.00002 <  >
1+2** -17 = 1.00001 <  >
1+2** -18 = 1 <  >
1+2** -19 = 1 <  >
1+2** -20 = 1 <  >
1+2** -21 = 1 <  >
1+2** -22 = 1 <  >
1+2** -23 = 1 <  >
1+2** -24 = 1 <  >
1+2** -25 = 1 <  >
1+2** -26 = 1 <  >
1+2** -27 = 1 <  >
1+2** -28 = 1 <  >
1+2** -29 = 1 <  >
1+2** -30 = 1 <  >
1+2** -31 = 1 <  >
1+2** -32 = 1 <  >
1+2** -33 = 1 <  >
1+2** -34 = 1 <  >
1+2** -35 = 1 <  >
1+2** -36 = 1 <  >
1+2** -37 = 1 <  >
1+2** -38 = 1 <  >
1+2** -39 = 1 <  >
1+2** -40 = 1 <  >
1+2** -41 = 1 <  >
1+2** -42 = 1 <  >
1+2** -43 = 1 <  >
1+2** -44 = 1 <  >
1+2** -45 = 1 <  >
1+2** -46 = 1 <  >
1+2** -47 = 1 <  >
1+2** -48 = 1 <  >
1+2** -49 = 1 <  >
1+2** -50 = 1 <  >
1+2** -51 = 1 <  >
1+2** -52 = 1 <  >
1+2** -53 = 1 < 1 >
1+2** -54 = 1 < 1 >
1+2** -55 = 1 < 1 >
1+2** -56 = 1 < 1 >
1+2** -57 = 1 < 1 >
1+2** -58 = 1 < 1 >
1+2** -59 = 1 < 1 >
1+2** -60 = 1 < 1 >
$ gawk --version | head -1
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4, GNU MP 6.1.0)

オチはありませんよ。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?