.NET中的小数不准确
昨天在debugging中发生了一些奇怪的事情,我不能真正解释一下:
所以也许我在这里看不到明显的,或者我误解.NET中的小数点,但不应该结果是一样的吗?
decimal
不是一个神奇的做我所有的mathtypes。 它仍然是一个浮点数 – 与float
的主要区别在于它是十进制浮点数,而不是二进制 。 所以你可以很容易地把0.3
作为一个十进制数(作为一个有限的二进制数是不可能的),但是你没有无限的精度。
这使得它更接近人类做相同的计算,但是你仍然必须想象别人正在单独做每一个操作。 它专门为财务计算而devise,在math中你不需要做那种事情 – 只需按照相当具体的规则将每个结果四舍五入。
事实上,在很多情况下, decimal
可能比float
更糟糕(或更好, double
)。 这是因为decimal
不会自动舍入。 用double
来做同样的事情会让你像预期的那样,因为它自动地假定差异无关紧要 – decimal
就是这样 – 这是关于decimal
的重要一点。 当然可以通过插入手动Math.Round
来模拟这个,但是没有什么意义。
十进制只能存储完全以十进制表示的值。 在这里22/24 = 0.91666666666666666666666 …需要无限的精度或者理性的types来存储,并且在四舍五入后不等于22/24。 如果你先进行乘法运算,那么所有的值都是完全可以表示的,因此你看到的结果是。
通过添加括号,确保在乘法之前计算除法。 这微妙地看起来足以影响计算,足以引入浮动精度问题 。
由于计算机实际上不可能产生每一个可能的数字,所以你应该确保你把这个计算在内
虽然Decimal
比Double
更精确,但其主要的有用特征是每个值都精确匹配其可读的表示 。 虽然在某些语言中可用的固定小数types可以保证两个匹配精度定点值的加法和减法,或者一个定点types与一个整数的乘法都不会导致舍入误差,而“如Java中的“十进制”types可以保证任何乘法都不会导致四舍五入错误,像.NET中find的浮点Decimal
types不提供这样的保证,并且没有十进制types可以保证除法操作可以在没有舍入错误的情况下完成(如果需要舍入,Java可以select抛出exception)。
虽然决定使Decimal
为浮点types的人可能已经打算可以用于在小数点右边需要更多数字的情况下,或者在左边更多的情况下,浮点types(无论是基于10还是基于base的) 2,所有操作都要避免四舍五入的问题。