Text1.Text = Int(0.1 * -50)
Text2.Text= Int(-5.0)
を実行すると
Text1.Text=-6,
Text2.Text=-5 となります
求められる結果が違うのはなぜなのでしょうか?
余剰加算によって生じた演算誤差が、
Intのレベルまで丸められた結果です。
演算誤差については、ネット上で調べれば見つかるかと思います。
丸め誤差だと思うから…下のような計算をしてみた。
IEEEの浮動小数点って、符号は1ビットでどこかに格納してたハズ。
よって、補数計算は必要ないと思われる。
(0.1)10進=(0.0[0011]...)2進
-(50)10進=-(110010)2進
-(5)10進=-(101)2進
-(50*0.1)10進=-(110010*0.0[0011]..)2進
1100100
110010
100.10110
=-(100.10110....)2進←多分
で、intは負の無限大に丸めるはずだから…どうなるんだ?
( ゜Д゜)マンドクセ…
※計算が違うかもしれない
ただのバグだと思うが・・・・(@o@)
思いつきだが、
debug.? (-5.0)\1,(-50*0.1)\1
で上手く計算される。
…この二つに関しては(ぇ
数学の世界では
(A + B) + C = A + (B + C) = (A + C) + B
(A - B) + C = A + (C - B) = (A + C) - B
(A * B) / C = A * (B / C) = (A / C) * B (ただし C は 0 ではない)
は必ず成り立ちますが、コンピュータ内での実数演算では、丸めの関係で、これらの法則が成立しない場合があります。
数値計算の世界では丸め誤差を最小限に抑え込む計算順序を考えるのもテクニックの内です。
浮動小数点演算誤差を避けるには、固定小数点演算を使いましょう。
Text1.Text = CStr(Int(0.1@ * -50@))
Text2.Text = CStr(Int(CDec("0.1") * CDec("-50")))
などであれば、誤差が発生しません。
浮動小数点型の場合、コンパイルモードによって結果が変わる事もあります。
Text1.Text = CStr(Int(0.1 * -50))
ってコードで実行したら、
P-Codeコンパイル時 → 「-6」
最適化無しコンパイル時 → 「-6」
速度最適化コンパイル時 → 「-5」
サイズ最適化コンパイル時 → 「-5」
という結果になりました。
なお、一度変数に入れると(今回の場合は)大丈夫みたい。
Debug.Print TypeName(0.1 * -50) '→ "Double"
D = 0.1 * -50
Debug.Print Int(D) '→ "-5"
Debug.Print Int(0.1 * -50) '→ "-6"
Debug.Print Int(CDbl(0.1 * -50)) '→ "-5"
コンピュータで少数を扱う場合、必然的に誤差を生じる。
基本的な事が分かっていませんでした。。。。
誤差が生じる事を前提に書くことをしないといけませんね。
ツイート | ![]() |