简体   繁体   English

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

[英]Wasn't the Double Type precision of 15 digits in C#?

I was testing this code from Brainteasers: 我正在测试Brainteasers的代码

        double d1 = 1.000001;

        double d2 = 0.000001;

        Console.WriteLine((d1 - d2) == 1.0);

And the result is "False". 结果是“假的”。 When I change the data type: 当我更改数据类型时:

        decimal d1 = 1.000001M;

        decimal d2 = 0.000001M;

        decimal d3 = d1-d2;

        Console.WriteLine(d3 == 1);

The program writes the correct answer: "True". 该程序写出正确的答案:“真”。

This problem just uses 6 digits after the floating point. 此问题仅在浮点后使用6位数。 What happened with the precision of 15 digits? 15位数的精度怎么样?

This has nothing to do with precision - it has to do with representational rounding errors. 这与精度无关 - 它与表示性舍入误差有关。

System.Decimal is capable of representing large floating point numbers with a significantly reduced risk of incurring any rounding errors like the one you are seeing. System.Decimal能够表示大浮点数,并且可以显着降低发生任何舍入错误的风险,例如您所看到的错误。 System.Single and System.Double are not capable of this and will round these numbers off and create issues like the one you are seeing in your example. System.SingleSystem.Double不具备此功能,并将关闭这些数字并创建类似于您在示例中看到的问题。

System.Decimal uses a scaling factor to hold the position of the decimal place thus allowing for exact representation of the given floating-point number, whereas System.Single and System.Double only approximate your value as best they can. System.Decimal使用缩放因子来保存小数位的位置,从而允许精确表示给定的浮点数,而System.SingleSystem.Double只能尽可能接近您的值。

For more information, please see System.Double : 有关详细信息,请参阅System.Double

Remember that a floating-point number can only approximate a decimal number, and that the precision of a floating-point number determines how accurately that number approximates a decimal number. 请记住,浮点数只能近似一个十进制数,并且浮点数的精度决定了该数字近似于十进制数的准确程度。 By default, a Double value contains 15 decimal digits of precision, although a maximum of 17 digits is maintained internally. 默认情况下,Double值包含15个十进制数字的精度,但内部最多保留17位数。 The precision of a floating-point number has several consequences: 浮点数的精度有几个结果:

  • Two floating-point numbers that appear equal for a particular precision might not compare equal because their least significant digits are different. 对于特定精度看起来相等的两个浮点数可能不相等,因为它们的最低有效位数不同。

  • A mathematical or comparison operation that uses a floating-point number might not yield the same result if a decimal number is used because the floating-point number might not exactly approximate the decimal number. 如果使用十进制数,使用浮点数的数学或比较操作可能不会产生相同的结果,因为浮点数可能不完全接近十进制数。

Generally, the way to check for equality of floating-point values is to check for near -equality, ie, check for a difference that is close to the smallest value (called epsilon ) for that datatype. 通常,检查浮点值是否相等的方法是检查near -equality,即检查接近该数据类型的最小值(称为epsilon )的差异。 For example, 例如,

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

This tests to see if the d1 and d2 are represented by the same bit pattern give or take the least significant bit. 这测试以查看d1d2是否由相同的位模式表示给出或取最低有效位。

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

Upon further examination, the code should be more like this: 经过进一步检查,代码应该更像这样:

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

In other words, take the absolute difference between d1 and d2 , then scale it by the largest of d1 and d2 , and then compare it to Epsilon . 换句话说,取d1d2之间的绝对差值,然后将其除以d1d2的最大值, 然后将其与Epsilon进行比较。

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

The decimal type implements decimal floating point whereas double is binary floating point. 十进制类型实现十进制浮点,而double是二进制浮点。

The advantage of decimal is that it behaves as a human would with respect to rounding, and if you initialise it with a decimal value, then that value is stored precisely as you specified. 十进制的优点是它在舍入方面表现得像人类一样,如果用十进制值初始化它,那么该值将按照您指定的方式精确存储。 This is only true for decimal numbers of finite length and within the representable range and precision. 这仅适用于有限长度的十进制数,并且在可表示的范围和精度内。 If you initialised it with say 1.0M/3.0M, then it would not be stored precisely just as you would write 0.33333-recurring on paper. 如果你用1.0M / 3.0M初始化它,那么就不会像在纸上写0.33333一样精确地存储它。

If you initialise a binary FP value with a decimal, it will be converted from the human readable decimal form, to a binary representation that will seldom be precisely the same value. 如果初始化带有小数的二进制FP值,它将从人类可读的十进制形式转换为很少完全相同的二进制表示。

The primary purpose of the decimal type is for implementing financial applications, in the .NET implementation it also has a far higher precision than double, however binary FP is directly supported by the hardware so is significantly faster than decimal FP operations. 十进制类型的主要目的是实现财务应用程序,在.NET实现中它也具有远高于double的精度,但二进制FP直接由硬件支持,因此明显快于十进制FP操作。

Note that double is accurate to approximately 15 significant digits not 15 decimal places . 请注意,double精确到大约15 位有效数字,而不是15 位小数 d1 is initialised with a 7 significant digit value not 6, while d2 only has 1 significant digit. d1初始化为7有效数字值而不是6,而d2仅有1有效数字。 The fact that they are of significantly different magnitude does not help either. 它们具有显着不同的幅度这一事实也无济于事。

The idea of floating point numbers is that they are not precise to a particular number of digits. 浮点数的想法是它们对于特定数量的数字并不精确。 If you want that sort of functionality, you should look at the decimal data type. 如果您想要这种功能,您应该查看decimal数据类型。

The precision isn't absolute, because it's not possible to convert between decimal and binary numbers exactly. 精度不是绝对的,因为不可能精确地在十进制和二进制数之间进行转换。

In this case, .1 decimal repeats forever when represented in binary. 在这种情况下,当以二进制表示时,.1十进制将永远重复。 It converts to .000110011001100110011... and repeats forever. 它转换为.000110011001100110011 ...并永远重复。 No amount of precision will store that exactly. 精确度不会精确存储。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM