.NET 中的小数不准确

问题描述 投票:0回答:4

昨天在调试过程中,我发生了一些奇怪的事情,我无法真正解释它:

所以也许我在这里没有看到明显的情况,或者我误解了 .NET 中小数的一些内容,但结果不应该是相同的吗?

c# .net decimal floating-accuracy
4个回答
72
投票

decimal
不是神奇的 为我做所有数学 类型。它仍然是一个浮点数 - 与
float
的主要区别在于它是一个 十进制 浮点数,而不是 二进制。因此,您可以轻松地将
0.3
表示为十进制(不可能表示为有限的二进制数),但您没有无限的精度。

这使得它的工作方式更接近于人类进行相同的计算,但您仍然必须想象有人单独执行每个操作。它是专门为金融计算而设计的,您不需要做数学中所做的事情 - 您只需一步一步地根据非常具体的规则对每个结果进行四舍五入即可。

事实上,在很多情况下,

decimal
的效果可能比
float
差很多(或者更好,
double
)。这是因为
decimal
根本不进行任何自动舍入。对
double
进行同样的操作,会得到预期的 22,因为它会自动假设差异并不重要 - 在
decimal
中,它 确实 - 这是关于
decimal
的重要点之一。当然,您可以通过插入手动
Math.Round
来模拟这一点,但这没有多大意义。


31
投票

Decimal
只能准确存储可以精确表示为十进制的值在其精度限制内。这里22/24 = 0.91666666666666666666666...需要无限精度有理类型来存储,并且四舍五入后它不再等于22/24。

如果您先进行乘法,那么所有中间结果都可以完全表示,因此您会看到结果。


13
投票

通过添加括号,您可以确保除法在乘法之前计算。这似乎足以影响计算,从而引入浮动精度问题

由于计算机实际上无法产生所有可能的数字,因此您应该确保将其纳入计算中


1
投票

虽然

Decimal
的精度比
Double
更高,但其主要有用功能是每个值都与其人类可读的表示形式精确匹配。虽然某些语言中可用的固定十进制类型可以保证两个匹配精度定点值的加法或减法,或者定点类型与整数的乘法都不会导致舍入误差,而“大十进制类型(例如 Java 中的类型)可以保证乘法不会导致舍入错误,浮点
Decimal
类型(例如 .NET 中的类型)不提供此类保证,并且没有小数类型可以保证除法运算可以在没有舍入错误的情况下完成(Java 可以选择在需要舍入的情况下抛出异常)。

虽然那些决定使

Decimal
成为浮点类型的人可能希望它可用于需要小数点右侧或左侧更多数字的情况,浮点类型,无论是以 10 为基数或以 2 为基数,使所有操作都不可避免地出现舍入问题。

© www.soinside.com 2019 - 2024. All rights reserved.