Decimal Precision Lost after 15th Digit - Bad PI

ε祈祈猫儿з 提交于 2019-12-14 03:35:00

问题


Attempting to print more than 15 decimal digits of PI result in incorrect decimals printing after the 15th decimal. This despite the 30 correct decimal values being assigned and despite using long double to hold the value. The following test case clearly shows the error.

This was unexpected. If there would be any error in the digits, I would not expect to see any error until the 25th digit after exhausting the IEEE-754 significand. What rule is in play here that might explain by I can't print back the same 30 digits I just assigned to sPI below. This also affects the ability to print the representations of M_PI contained in math.h.

#include <stdio.h>

int
main (void) {

    // static PI approximation (glibc man 1.17)
    long double sPI = 3.14159265358979323846264338327;
    char strPI[]   = "3.14159265358979323846264338327";

    printf ("\n %s (strPI - string - correct)\n", strPI);
    printf (" %.29Lf (sPI - long double - INCORRECT)\n\n", sPI);

    return (0);
}

output:

3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979311599796346854 (sPI - long double - INCORRECT)
                 ^^^^^^^^^^^^^^

Presumably, this decimal error would apply to any decimal number with greater than 16 decimal precision. When printed as a string, PI prints fine (obviously), but when printed as a double -- the decimal precision breaks down after the 15th decimal. What is causing that?

Very interesting, as suggested adding an L at the end of the floating point literal did help:

 3.14159265358979323846264338327 (strPI - string - correct)
 3.14159265358979323851280895941 (sPI - long double - INCORRECT)

That provided 3 additional decimals of precision. For clarity, this was run on Linux 3.14.1 kernel, gcc 4.8.2 on an old AMD Phenom X4 9850. (AMD Turion Based Laptop & Intel P4 gives same result)

Attempting with quadmath.h and __float128 type assigned to sPI, the results were the same as for the long double. A few more digits were available, but precision still broke down on the 19th digit:

3.14159265358979323846264338327 (strPI - string - correct)
3.1415926535897932385128089594061862 (sPI - long double - INCORRECT)

回答1:


Double precision floating point values are represented as a 64 bit value, with finite precision of 15-16 decimal digits. It would therefore appear that long double is implemented as 64 bit double precision on your system.

In case you are not familiar with these issues, I highly recommend David Goldberg's timeless article What Every Computer Scientist Should Know About Floating-Point Arithmetic.




回答2:


You are not storing the 'long double' value into the variable, but the default double instead. The compiler reads the floating point value, stores it as a default type, and only casts it to long double "afterwards". You can see this when you compare its value to a "normally" assigned double.

To hint the compiler to store the constant as a long double, add the modifier suffix L or l at the end of the floating point constant.

Example:

#include <stdio.h>

int main (void)
{
    // static PI approximation (glibc man 1.17)
    double sPI_d     = 3.14159265358979323846264338327;
    long double sPI  = 3.14159265358979323846264338327;
    long double sPI_L= 3.14159265358979323846264338327L;
    char strPI[]     ="3.14159265358979323846264338327";

    printf ("\n %s (strPI - string - correct)\n", strPI);
    printf (" %.29f (sPI - double)\n", sPI_d);
    printf (" %.29Lf (sPI - long double - INCORRECT)\n", sPI);
    printf (" %.29Lf (sPI - long double - BETTER)\n", sPI_L);

    return 0;
}

Output:

 3.14159265358979323846264338327 (strPI - string - correct)
 3.14159265358979311599796346854 (sPI - double)
 3.14159265358979311599796346854 (sPI - long double - INCORRECT)
 3.14159265358979323851280895941 (sPI - long double - BETTER)

See also What is the precision of long double in C++? -- you cannot expect more than around 18 significant digits for a long double.



来源:https://stackoverflow.com/questions/24485846/decimal-precision-lost-after-15th-digit-bad-pi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!