・結果に困惑                            GAI 氏

 あるプログラムをPARI/GPで走らせていたところ、どうしてもプログラムが特定の値では
結果をいくら待っても終了せず、その原因を一つずつ潰していたところ、なんと思ってもい
ない次のような計算が行われていたことが判明しました。

 この様なことになってしまうのは、私が使っているソフトに限るのでしょうか?

 皆さんが使われているソフトでは如何なる結果を返してくるかを教えて欲しい。

gp > for(n=1,20,print(n";"floor(log(10^n)/log(10))))
1;1
2;2
3;2
4;4
5;5
6;5
7;7
8;8
9;9
10;10
11;10
12;11
13;12
14;14
15;14
16;16
17;16
18;18
19;19
20;20

→ 3,6,11,12,13,15,17でこちらの思惑が裏切られてしまいました。


(コメント) コンピュータの内部演算のせいでは?(→ 参考:「小数計算に弱い計算ソフト」)


 Dengan kesaktian Indukmu さんからのコメントです。(令和6年9月20日付け)

 手元では同様ですね。PARI は、ひとたび小数を扱うことになると、2進数で内部表現する
のかな? と思いましたが、ざっと見、それだけではうまく説明できないような?

? for(n=1,20,print(n";"floor(log(10^n)/log(10))))
1;1
2;2
3;2
4;4
5;5
6;5
7;7
8;8
9;9
10;10
11;10
12;11
13;12
14;14
15;14
16;16
17;16
18;18
19;19
20;20

 JavaScript では以下の通りです。

for (let n = 1; n <= 20; n++) {
console.log(n + ";" + Math.floor(Math.log(Math.pow(10, n)) / Math.log(10)));
}

 上を RUN すると、

"1;1"
"2;2"
"3;2"
"4;4"
"5;5"
"6;5"
"7;7"
"8;8"
"9;8"
"10;10"
"11;11"
"12;11"
"13;12"
"14;14"
"15;14"
"16;16"
"17;17"
"18;17"
"19;19"
"20;20"

となります。

 JavaScript ではたぶん小数点以下は、最寄りの2進数で捉えているので……。


 GAI さんからのコメントです。(令和6年9月20日付け)

 他の計算ソフトでも調査してみた。

*sageMathのソフト
sage: for i in range(21) :print(i,floor(ln(10^i)/ln(10)));
(0, 0)
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)
(6, 6)
(7, 7)
(8, 8)
(9, 9)
(10, 10)
(11, 11)
(12, 12)
(13, 13)
(14, 14)
(15, 15)
(16, 16)
(17, 17)
(18, 18)
(19, 19)
(20, 20)

全部上手く走る

*Rubyのソフト
irb(main):001:0> include Math
=> Object
irb(main):012:0> 0.upto(20){|i| print i,";",log(10**i)/log(10),"\n"}
0;0.0
1;1.0
2;2.0
3;2.9999999999999996
4;4.0
5;5.0
6;5.999999999999999
7;7.0
8;8.0
9;8.999999999999998
10;10.0
11;11.0
12;11.999999999999998
13;12.999999999999998
14;14.0
15;14.999999999999998
16;16.0
17;17.0
18;17.999999999999996
19;19.0
20;20.0

 3,6,9,12,13,15,18で上手くいかなくなる。

*Maximaのソフト
(%i13) for i :1 thru 20 do
print(float(log(10^i)/log(10)));

1.0" "
2.0" "
3.0" "
4.0" "
5.0" "
6.0" "
7.0" "
8.0" "
8.999999999999998" "
9.999999999999998" "
11.0" "
12.0" "
13.0" "
14.0" "
15.0" "
16.0" "
17.0" "
18.0" "
19.0" "
20.0" "

 9,10で難点


 Dengan kesaktian Indukmu さんからのコメントです。(令和6年9月20日付け)

 PARI で、床関数を使う前に微量な下駄をはかせましたが 258,259で破綻。

for(n=257,260,print(n";"floor(10^(-36)+log(10^n)/log(10))))

257;257
258;257
259;258
260;260


 Dengan kesaktian Indukmu さんからのコメントです。(令和6年9月22日付け)

 PARI にて、n = 308 までの範囲で微小量を足すテストをしました。
(javascriptだと10^308を超えると途中計算結果に無限大が現れる扱いになったので……
PARIではどうなのかわからず、とりあえずです)

 微小量としては、2 ^{-119} と 2 ^{- 120} とのあいだに分水嶺があります。以下。

? i = -120; for(n = 1, 308, if(n == floor(2^i + log(10^n)/log(10)), next,
print(n, ";", floor(2^i + log(10^n)/log(10))) ) ); print("END")
 
 上を走らせると

258;257
259;258
265;264
266;265
271;270
272;271
277;276
278;277
283;282
284;283
290;289
291;290
296;295
297;296
302;301
303;302
308;307
END
 
となり

? i = -119; for(n = 1, 308, if(n == floor(2^i + log(10^n)/log(10)), next,
print(n, ";", floor(2^i + log(10^n)/log(10))) ) ); print("END")

 上を走らせると
 
END

となります。



  以下、工事中!



              投稿一覧に戻る