【发布时间】:2015-11-18 19:23:41
【问题描述】:
【问题讨论】:
-
您可以关注Floating point issue
-
相关:stackoverflow.com/q/618535/1394393。不是骗子。 (至少,这在一个通常被误解的方面有所体现。)
标签: c# .net decimal floating-accuracy
【问题讨论】:
标签: c# .net decimal floating-accuracy
decimal 不是一个神奇的为我做所有的数学类型。它仍然是一个浮点数 - 与float 的主要区别在于它是一个十进制 浮点数,而不是二进制。所以你可以很容易地将0.3 表示为十进制(不可能作为有限的二进制数),但你没有无限的精度。
这使它更接近于人类进行相同的计算,但您仍然必须想象有人单独执行每个操作。它专为财务计算而设计,您无需像在数学中那样做 - 您只需一步一步地根据非常具体的规则对每个结果进行四舍五入。
事实上,在很多情况下,decimal 的效果可能比float 差很多(或者更好,double)。这是因为decimal 根本不进行任何自动舍入。对double 执行相同操作会得到预期的 22,因为它自动假定差异无关紧要 - 在 decimal 中,它确实 - 这是关于 decimal 的重点之一.当然,您可以通过插入手动 Math.Rounds 来模拟这一点,但这没有多大意义。
【讨论】:
Decimal 只能在其精度限制内准确存储可以用十进制精确表示的值。这里 22/24 = 0.91666666666666666666666... 需要无限精度或有理类型来存储,四舍五入后不再等于 22/24。
如果你先做乘法,那么所有的值都是可以精确表示的,因此你会看到结果。
【讨论】:
通过添加括号,您可以确保在乘法之前计算除法。这看起来足以影响计算,足以引入floating precision issue。
由于计算机实际上无法生成所有可能的数字,因此您应该确保将其纳入计算中
【讨论】:
1 / 3 就是一个很好的例子,因为每个人都会决定什么精度对他们来说是足够的,并且永远不会试图弄清楚是否有解决方案。 (剧透:没有。它总是递归的 3)
1 / 3,或者写为0.33(无限扩展)。即使是无理数,我们也可以写出它们是如何定义的,或者只使用一个常数。当您对精度非常认真时非常方便:D
1/3 是浮点基数3 中的0.1。
虽然Decimal 比Double 具有更高的精度,但它的主要有用特性是每个值精确匹配其人类可读的表示。虽然在某些语言中可用的固定十进制类型可以保证两个匹配精度的定点值的加法或减法,或者定点类型乘以一个整数,都不会导致舍入错误,而“大十进制”类型(例如 Java 中的类型)可以保证乘法不会导致舍入错误,浮点 Decimal 类型(例如 .NET 中的类型)不提供此类保证,并且没有十进制类型可以保证除法运算可以在没有舍入错误的情况下完成(如果需要舍入,Java 可以选择抛出异常)。
虽然那些决定将Decimal 设为浮点类型的人可能打算将其用于需要在小数点右侧或左侧更多位的情况下,但浮点类型,无论是基数-10 或以 2 为底,使所有运算都不可避免地出现舍入问题。
【讨论】: