Search code examples
c#typesfloating-pointdecimalprecision

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


I was testing this code from 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. What happened with the precision of 15 digits?


Solution

  • 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.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.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.

    For more information, please see 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. 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.