投稿者:mike
投稿日:2017年 4月30日(日)14時01分15秒
|
|
|
スピードチェックをしていて、次のプログラムを実行したところ
2進モードと10進モードで異なった計算結果が得られました。
---------------------
LET t0=TIME
LET x=0
FOR i=1 TO 100000000
LET x=x+i
NEXT i
PRINT TIME - t0
print "X=";x
END
---------------
2進モードのとき
9.24
X= 5.00000005E15
10進モードのとき
35.73
X= 5.00000007763932E15
decimalBASIC 6.6.2.2 /MacOS 10.7.5
decimalBASIC 7.8.0 /windows 10
どちらも同じ計算結果でした。
2進モードの方が速く正しい結果が得られています。
10進モードのとき、計算誤差にしては大きすぎるので、
何か不具合があると思われます。
|
|
|
投稿者:しばっち
投稿日:2017年 4月30日(日)17時17分2秒
|
|
|
> No.4349[元記事へ]
mikeさんへのお返事です。
10進モードで実行すると
FOR I=1 TO 100000000
LET X=X+I
LET Y=I*(I+1)/2
IF X<>Y THEN
PRINT I
PRINT X;Y
STOP
END IF
NEXT I
END
実行結果
44721363
1.00000017664956E15 1.00000017664957E15
となりました
1000桁モードで
PRINT 44721363*(44721363+1)/2
END
実行結果
1000000176649566
これを見ると精度不足による誤差の累積が原因ではないでしょうか?
|
|
|
投稿者:SHIRAISHI Kazuo
投稿日:2017年 4月30日(日)18時13分53秒
|
|
|
> No.4353[元記事へ]
十進モードは四捨五入による丸めなので,単純に和を求めるような計算だと誤差の累積がプラスの側に偏る傾向が出ると思います。
2進モードで
LET x=0
FOR I=1 TO 100000000
LET X=X+I
IF x>1e15 THEN LET x=INT((x+5)/10)*10
NEXT I
PRINT x
END
を実行すると
5000000077639320
になるので,計算は合っていると思います。
> mikeさんへのお返事です。
>
> 10進モードで実行すると
>
> FOR I=1 TO 100000000
> LET X=X+I
> LET Y=I*(I+1)/2
> IF X<>Y THEN
> PRINT I
> PRINT X;Y
> STOP
> END IF
> NEXT I
> END
>
> 実行結果
> 44721363
> 1.00000017664956E15 1.00000017664957E15
>
> となりました
>
> 1000桁モードで
>
> PRINT 44721363*(44721363+1)/2
> END
>
> 実行結果
> 1000000176649566
>
> これを見ると精度不足による誤差の累積が原因ではないでしょうか?
>
>
|
|
|
投稿者:mike
投稿日:2017年 4月30日(日)20時01分57秒
|
|
|
> No.4354[元記事へ]
しばっちさん、白石先生、ご回答ありがとうございます。
> これを見ると精度不足による誤差の累積が原因ではないでしょうか?
了解しました。計算精度の理解が不足していたようです。
ちなみに2進モードでしばっちさんのプログラムの上限を大きくして実行すると
FOR I=1 TO 1000000000
LET X=X+I
LET Y=I*(I+1)/2
IF X<>Y THEN
PRINT I
PRINT X;Y
STOP
END IF
NEXT I
END
134217730
9.00719959028531E15 9.00719959028532E15
となり、偶然にも、1E8は、計算精度から2進モードでは誤差が出ず、
10進モードでは誤差が累積する数であったことがわかりました。
> 十進モードは四捨五入による丸めなので,単純に和を求めるような計算だと誤差の累積がプラ
> スの側に偏る傾向が出ると思います。
プログラムの文脈から10進モードでは、15桁目で四捨五入していると理解してよろしいでしょうか。
お世話になりました。
|
|
|
戻る