Significant digits with IEEE 754 float

1.1k views Asked by At

The Wiki Double-precision floating-point format says:

This gives 15–17 significant decimal digits precision. If a decimal string with at most 15 significant digits is converted to IEEE 754 double precision representation and then converted back to a string with the same number of significant digits, then the final string should match the original. If an IEEE 754 double precision is converted to a decimal string with at least 17 significant digits and then converted back to double, then the final number must match the original.

Can anybody give me some example to show how the conversion match the original, and in which cases it doesn't?

1

There are 1 answers

2
Tony Delroy On

With 15 significant digits, from string to double and back...

std::istringstream iss("0.123456789012345");
double d;
iss >> d;
std::ostringstream oss;
oss << std::fixed << std::setprecision(15) << d;
std::cout << "should be 0.123456789012345 but might have changed: " << oss.str() << '\n';

Note: for some 15 significant-digit initial input strings, the above code may output a different final string. Here's a program that attempts to find a 15 digit string input for which the value isn't preserved by conversion to and from a double, but all values pass for GCC on coliru.stackedcrooked.com. That doesn't mean it wouldn't fail for some other values in a different range.

#include <sstream>
#include <iostream>
#include <iomanip>

int main()
{
    int results = 0;

    for (unsigned long i = 0; i <= 999999999999999; ++i)
    {
        std::ostringstream oss;
        oss << "0." << std::setfill('0') << std::setw(15) << i;
        std::istringstream iss(oss.str());
        double d;
        iss >> d;
        std::ostringstream oss2;
        oss2 << std::fixed << std::setprecision(15) << d;
        if (oss.str() != oss2.str())
        {
            std::cout << "from " << oss.str() << '\n' << "  to " << oss2.str() << '\n';
            if (++results > 50) exit(0);
        }
    }
}

With 17 significant digits, from double to string and back...

double d = 0.12345678901234567;
std::ostringstream oss;
oss << std::fixed << std::setprecision(17) << d;
std::istringstream iss(oss.str());
double d2;
iss >> d2;
std::cout << "d must equal d2: " << std::boolalpha << d == d2 << '\n';

This should never fail to recover an identical double value from the textual representation.