C#中的15位数的Double Type精度是不是?

我正在测试Brainteasers的代码:

double d1 = 1.000001; double d2 = 0.000001; Console.WriteLine((d1 - d2) == 1.0); 

结果是“假的”。 当我更改数据类型时:

  decimal d1 = 1.000001M; decimal d2 = 0.000001M; decimal d3 = d1-d2; Console.WriteLine(d3 == 1); 

该程序写出正确的答案:“真”。

此问题仅在浮点后使用6位数。 15位数的精度怎么样?

这与精度无关 – 它与表示舍入误差有关。

System.Decimal能够表示大的浮点数,并且可以显着降低发生任何舍入错误的风险,例如您所看到的错误。 System.SingleSystem.Double不具备此function,并将关闭这些数字并创建类似于您在示例中看到的问题。

System.Decimal使用缩放因子来保存小数位的位置,从而允许精确表示给定的浮点数,而System.SingleSystem.Double只能尽可能接近您的值。

有关更多信息,请参阅System.Double

请记住,浮点数只能近似一个十进制数,并且浮点数的精度决定了该数字接近十进制数的准确程度。 默认情况下,Double值包含15个十进制数字的精度,但内部最多保留17位数。 浮点数的精度有几个结果:

  • 对于特定精度看起来相等的两个浮点数可能不会相等,因为它们的最低有效数字是不同的。

  • 如果使用十进制数,使用浮点数的数学运算或比较运算可能不会产生相同的结果,因为浮点数可能不完全接近十进制数。

通常,检查浮点值是否相等的方法是检查near -equality,即检查接近该数据类型的最小值(称为epsilon )的差异。 例如,

 if (Math.Abs(d1 - d2) <= Double.Epsilon) ... 

这测试以查看d1d2是否由相同的位模式表示给出或取最低有效位。

更正 (2015年3月2日新增)

经过进一步检查,代码应该更像这样:

 // Assumes that d1 and d2 are not both zero if (Math.Abs(d1 - d2) / Math.Max(Math.Abs(d1), Math.Abs(d2)) <= Double.Epsilon) ... 

换句话说,取d1d2之间的绝对差值,然后将其除以d1d2的最大值, 然后将其与Epsilon进行比较。

参考
• http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
• http://msdn.microsoft.com/en-us/library/system.double.aspx#Precision

十进制类型实现十进制浮点,而double是二进制浮点。

十进制的优点是它在舍入方面表现得像人类一样,如果用十进制值初始化它,那么该值将按照您指定的方式精确存储。 这仅适用于有限长度的十进制数,并且在可表示的范围和精度内。 如果你用1.0M / 3.0M初始化它,那么就不会像在纸上写0.33333一样精确地存储它。

如果初始化带有小数的二进制FP值,它将从人类可读的十进制forms转换为很少完全相同的二进制表示。

十进制类型的主要目的是用于实现财务应用程序,在.NET实现中它也具有比double高得多的精度,但是硬件直接支持二进制FP,因此明显快于十进制FP操作。

请注意,double精确到大约15 位有效数字而不是15 位小数d1初始化为7有效数字值而不是6,而d2仅有1有效数字。 它们具有显着不同的幅度这一事实也无济于事。

浮点数的想法是它们对于特定数量的数字不精确。 如果您想要这种function,您应该查看decimal数据类型。

精度不是绝对的,因为不可能精确地在十进制和二进制数之间进行转换。

在这种情况下,当以二进制表示时,.1十进制将永远重复。 它转换为.000110011001100110011 …并永远重复。 精确度不会精确存储。

避免比较浮点数的相等性。