C# NET中十进制的不精确性
昨天在调试过程中,我遇到了一件奇怪的事情,我真的无法解释:C# NET中十进制的不精确性,c#,.net,decimal,floating-accuracy,C#,.net,Decimal,Floating Accuracy,昨天在调试过程中,我遇到了一件奇怪的事情,我真的无法解释: 因此,也许我没有在这里看到明显的结果,或者我误解了.NET中的小数,但结果不应该是相同的吗?decimal不是一个神奇的“为我做所有的数学”类型。它仍然是一个浮点数-与float的主要区别在于它是一个十进制浮点数,而不是二进制。因此,您可以轻松地将0.3表示为十进制数(不可能表示为有限的二进制数),但您没有无限的精度 这使得它的工作更接近于一个人做同样的计算,但你仍然必须想象有人单独做每一个操作。它是专门为金融计算而设计的,在金融计
因此,也许我没有在这里看到明显的结果,或者我误解了.NET中的小数,但结果不应该是相同的吗?
decimal
不是一个神奇的“为我做所有的数学”类型。它仍然是一个浮点数-与float
的主要区别在于它是一个十进制浮点数,而不是二进制。因此,您可以轻松地将0.3
表示为十进制数(不可能表示为有限的二进制数),但您没有无限的精度
这使得它的工作更接近于一个人做同样的计算,但你仍然必须想象有人单独做每一个操作。它是专门为金融计算而设计的,在金融计算中,你不会做你在数学中做的那种事情——你只是一步一步地去做,根据非常具体的规则把每个结果四舍五入
事实上,在许多情况下,
decimal
的效果可能比float
差得多(或者更好,double
)。这是因为decimal
根本不做任何自动取整。使用double
进行同样的操作,会得到预期的22,因为它会自动假定差异不重要-在十进制中,它是重要的-这是关于十进制
的一个要点。当然,你可以通过插入manualMath.Round
s来模拟这一点,但这没有多大意义。通过添加括号,你可以确保在乘法之前计算除法。这微妙地看起来足以影响计算,足以引入一种新的方法
由于计算机无法实际生成所有可能的数字,因此您应该确保将其纳入计算中Decimal
只能在其精度限制内准确存储以十进制表示的值。这里22/24=0.916666666。。。它需要无限精度或有理类型来存储,并且舍入后不再等于22/24
如果先进行乘法运算,那么所有的值都是可精确表示的,因此您会看到结果。虽然十进制
的精度高于双精度
,但它的主要有用功能是每个值都精确匹配其人类可读的表示形式。虽然某些语言中可用的固定小数类型可以保证两个匹配的精确定点值的加减,或定点类型与整数的相乘都不会导致舍入误差,而“大小数”Java中的类型可以保证乘法不会导致舍入错误,而.NET中的浮点Decimal
类型则不提供这种保证,并且没有十进制类型可以保证除法操作可以在没有舍入错误的情况下完成(Java可以选择抛出异常,以防需要舍入)
虽然决定将
十进制设为浮点数类型的人可能有意将其用于需要小数点右侧更多位数或左侧更多位数的情况,但浮点数类型(无论是基-10还是基-2)使得所有操作都不可避免地存在舍入问题。您可以遵循相关的:.N一个很好的例子是,1/3
是一个很好的例子,因为每个人都会决定什么样的精度对他们来说是足够的,而且永远不会试图找出是否有解决方案。(剧透:没有。它总是递归的3)不过,人类可以做的很酷的事情是在剩下的计算中保持它为1/3
,或者写0.33
(无限扩展)。即使对于无理数,我们也可以写出它们的定义,或者只使用常数。当你真正认真考虑精度时,这非常方便:D@Luaan或在计算时切换到三元,并写入0.1.:)@卢安:计算机也可以做那件很酷的事情。只是当你告诉他们用有限精度浮点数进行计算时,他们会服从。人类和计算机都知道1/3
是0.1
的浮点基-3。