.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。 如果你先进行乘法运算,那么所有的值都是完全可以表示的,因此你看到的结果是。

通过添加括号,确保在乘法之前计算除法。 这微妙地看起来足以影响计算,足以引入浮动精度问题 。

由于计算机实际上不可能产生每一个可能的数字,所以你应该确保你把这个计算在内

虽然DecimalDouble更精确,但其主要的有用特征是每个值都精确匹配其可读的表示 。 虽然在某些语言中可用的固定小数types可以保证两个匹配精度定点值的加法和减法,或者一个定点types与一个整数的乘法都不会导致舍入误差,而“如Java中的“十进制”types可以保证任何乘法都不会导致四舍五入错误,像.NET中find的浮点Decimaltypes不提供这样的保证,并且没有十进制types可以保证除法操作可以在没有舍入错误的情况下完成(如果需要舍入,Java可以select抛出exception)。

虽然决定使Decimal为浮点types的人可能已经打算可以用于在小数点右边需要更多数字的情况下,或者在左边更多的情况下,浮点types(无论是基于10还是基于base的) 2,所有操作都要避免四舍五入的问题。