Search code examples
c++floating-pointieee-754

Blatant floating point error in C++ program


I am assigning a double literal to a double variable. The variable's value gets truncated, otherwise I cannot understand why, for example the difference diff is 0.0.

Sorry for the code duplication at setprecision but I am really pissed off.

#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>

int main()
{
    long double d = 1300010000000000000144.5700788999;
    long double d1 = 1300010000000000000000.0;
    long double diff = d - d1; // shall be 144.5700788999!!!
    long double d2 = 0.5700788999;

    std::cout << "d = " << std::fixed << std::setprecision(std::numeric_limits<long double>::digits10 + 1) << d << '\n';
    std::cout << "d1 = " << std::fixed << std::setprecision(std::numeric_limits<long double>::digits10 + 1) << d1 << '\n';
    std::cout << "d - d1 = " << std::fixed << std::setprecision(std::numeric_limits<long double>::digits10 + 1) << diff << '\n';
    std::cout << "d2 = " << std::fixed << std::setprecision(std::numeric_limits<long double>::digits10 + 1) << d2 << '\n';
}

This is the output:

d = 1300009999999999900000.0000000000000000
d1 = 1300009999999999900000.0000000000000000
d - d1 = 0.0000000000000000
d2 = 0.5700788999000001

I am expecting diff to be 144.5700788999 but it is 0.0

So, how to deal with it? (Window 7 and higher, VS 2013)

...To use two doubles, one for high values and one for low values? Like, instead using d to use d1 and d2?


Solution

  • 80-bit long double (not sure about its size in MSVS) can store around 18 significant decimal digits without loss of precision. 1300010000000000000144.5700788999 has 32 significant decimal digits and cannot be stored exactly as long double.

    Read Number of Digits Required For Round-Trip Conversions for more details.