我使用小数类型进行高精度计算(货币)。
但我今天遇到了这个简单的部门:
1 / (1 / 37)
应该再次导致37
http://www.wolframalpha.com/input/?i=1%2F+%281%2F37%29
但是C#给了我:
37.000000000000000000000000037M
我试过这两个:
1m/(1m/37m);
和
Decimal.Divide(1, Decimal.Divide(1, 37))
但两者都产生相同的结果。这种行为是如何解释的?
答案 0 :(得分:4)
Decimal
将值存储为十进制浮点,且精度有限。未精确存储1/37的结果,因为它存储为0.027027027027027027027027027M。真实数字使组027以十进制表示无限期地进行。因此,对于每个可能的数字,您无法获得十进制表示的精确数字。
如果在同一计算中使用Double
,则在这种情况下最终结果是正确的(但这并不意味着它总是更好)。
关于该主题的一个好答案是:Difference between decimal, float and double in .NET?
答案 1 :(得分:1)
十进制数据类型的准确度为28-29个有效数字。 因此,您必须了解的是,当您考虑28-29个有效数字时,您仍然不准确。
因此,当您计算(1/37)的十进制值时,您需要注意的是,在此阶段您只能获得28-29位数的精度。例如,当你取2位有效数字时,1/37是0.02,当你取3位有效数字时,得到0.027。想象一下,在每种情况下,您将这些值除以1。在第一种情况下得到50,在第二种情况下得到37.02 ......考虑到28-29位数(十进制),你的准确度为37.000000000000000000000000037。如果你必须得到精确的37,你只需要比小数要多28-29位有效数字。
始终使用最大有效数字进行计算,并使用Math.Round将您的答案四舍五入以获得所需结果。