[@IT]VB6とVB2005での計算結果の違い より
***当初のものより修正されています。***
少し興味をもったのでテストしてみました。
提示されている計算式は次のようになっています。
金額 = (単価 X 数量) / 1000
例として、数量の部分に以下の数値が挙げられています。
23.33333....・・・70割る3で求められる
33.33333....・・・100割る3で求められる
また、単価の部分には4500という数値が挙げられています。
これを、小学校で習った分数で約分して解くと次のようになります。(解き方はいくつかありますが)
金額 =(4500 X(70 / 3)) / 1000
= 4500 X 70 / 3 / 1000
= 1500 X 70 / 1000
= 15 X 7 = 105
金額 =(4500 X(100 / 3)) / 1000
= 4500 X 100 / 3 / 1000
= 1500 X 100 / 1000
= 15 X 10 = 150
これを、VB2005を使用して、Double型、Decimal型の両方で計算してみました。
--------------------------------------------------------------------------------
Module Module1
Sub Main()
Console.WriteLine("1st----------")
Dim d1 As Double = 4500
Dim d2 As Double = 70 / 3
Dim d3 As Double = d1 * d2 / 1000
Console.WriteLine("d1:{0}", d1)
Console.WriteLine("d2:70 / 3 = {0}", d2)
Console.WriteLine("d3:d1 * d2 / 1000 = {0}", d3)
Console.WriteLine("----------end")
Console.WriteLine("2nd----------")
Dim d4 As Double = 4500
Dim d5 As Double = 100 / 3
Dim d6 As Double = d4 * d5 / 1000
Console.WriteLine("d4:{0}", d4)
Console.WriteLine("d5:100 / 3 = {0}", d5)
Console.WriteLine("d6:d4 * d5 / 1000 = {0}", d6)
Console.WriteLine("----------end")
Console.WriteLine("3rd----------")
Dim de1 As Decimal = 4500
Dim de2 As Decimal = Convert.ToDecimal(70 / 3)
Dim de2 As Decimal = 70D / 3D
Dim de3 As Decimal = de1 * de2 / 1000
Console.WriteLine("de1:{0}", de1)
Console.WriteLine("de2:70 / 3 = {0}", de2)
Console.WriteLine("de3:de1 * de2 / 1000 = {0}", de3)
Console.WriteLine("----------end")
Console.WriteLine("4th----------")
Dim de4 As Decimal = 4500
Dim de5 As Decimal = Convert.ToDecimal(100 / 3)
Dim de5 As Decimal = 100D / 3D
Dim de6 As Decimal = de4 * de5 / 1000
Console.WriteLine("de4:{0}", de4)
Console.WriteLine("de5:100 / 3 = {0}", de5)
Console.WriteLine("de6:de4 * de5 / 1000 = {0}", de6)
Console.WriteLine("----------end")
Console.ReadKey()
End Sub
End Module
--------------------------------------------------------------------------------
結果はこうなりました。
--------------------------------------------------------------------------------
1st----------
d1:4500
d2:70 / 3 = 23.3333333333333
d3:d1 * d2 / 1000 = 105
----------end
2nd----------
d4:4500
d5:100 / 3 = 33.3333333333333
d6:d4 * d5 / 1000 = 150
----------end
3rd----------
de1:4500
de2:70 / 3 = 23.3333333333333
de3:de1 * de2 / 1000 = 104.99999999999985
de3:de1 * de2 / 1000 = 105.00000000000000000000000
----------end
4th----------
de4:4500
de5:100 / 3 = 33.3333333333333
de6:de4 * de5 / 1000 = 149.99999999999985
de6:de4 * de5 / 1000 = 150.00000000000000000000000
----------end
--------------------------------------------------------------------------------
なんと、この例では嫌われている模様のDouble型のほうが正確な答えを出しました。
同じ答えになっちゃったんですけど・・・(汗
ちなみに、MSDNでは以下のようなことが書かれています。
--------------------------------------------------------------------------------
Decimal 値型は、多数の有効な整数桁と小数桁を必要とし、丸め誤差を使用しない財務計算に適しています。Decimal 型では、丸めの必要性はなくなっていません。その代わりに、丸め誤差が最小限に抑えられています。
--------------------------------------------------------------------------------
つまり、Decimal型は誤差がないわけではなく、最小限に抑えられているだけなのですね。
Decimal型は、丸め誤差が最小限に抑えられているようです。
どこか忘れましたが、.Netでは複合式の計算順序は最適化される、との文章を見たことがあります。
今回Double型のほうが正確だったのは、それが行われたからなのでしょうか。
それとも、偶然なのでしょうか。
なんだか、分からなくなってきました・・・(T-T)