Попытка напечатать более 15 десятичных цифр PI
приведет к неправильной печати десятичных знаков после 15-го десятичного знака. Это несмотря на то, что 30 правильных десятичных значений назначены и, несмотря на использование long double
для хранения значения. В следующем тестовом примере явно показана ошибка.Десятичная точность потеряна после 15-й цифры - Bad PI
Это неожиданно. Если бы произошла ошибка в цифрах, я бы не ожидал увидеть какую-либо ошибку до 25-й цифры после исчерпания значения IEEE-754. Какое правило играет здесь, что может объяснить, что я не могу распечатать те же 30 цифр, которые я только что назначил для sPI ниже. Это также влияет на способность печатать изображения M_PI
, содержащиеся в 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);
}
выход:
3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979311599796346854 (sPI - long double - INCORRECT)
^^^^^^^^^^^^^^
Предположительно, это десятичное ошибка будет применяться к любому десятичного числа с более чем 16 десятичных точностью. При печати в виде строки PI печатает отлично (очевидно), но при печати в виде двойной - десятичная точность ломается после 15-го десятичного знака. Что вызывает это?
Очень интересно, как предложил добавить L
в конце плавающей точкой буквального помогло:
3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979323851280895941 (sPI - long double - INCORRECT)
Это при условии 3 дополнительных знаков после запятой точности. Для ясности, это работает на Linux 3.14.1 ядра, GCC 4.8.2 на старом AMD Phenom X4 9850. (AMD Turion ноутбук на базе Intel P4 & дает тот же результат)
Попытка с quadmath.h
и __float128
типа присваивается sPI
, результаты были такими же, как и для длинного двойника. Еще несколько цифр были доступны, но точность все равно сломалась на 19-й цифре: значения с плавающей точкой
3.14159265358979323846264338327 (strPI - string - correct)
3.1415926535897932385128089594061862 (sPI - long double - INCORRECT)
Похоже, что 'long double' все еще 64-битная двойная точность. Не все компиляторы поддерживают 80-битную расширенную точность, и для тех, которые могут потребоваться компилятор. – Mysticial
Вы не сказали, какой компилятор вы используете. Многие компиляционные платформы предлагают 80-битный 'long double' (GCC на Linux/x86, Clang на Linux/x86, ...), но даже больше определяют' long double' как тот же тип, что и 'double' (Visual Studio). Примечание: даже если 'long double' был 80-битным расширенным префиксом с плавающей запятой, вы не получили бы цифры из десяти десятичных цифр, что больше похоже на 19-21. –
Вы понимаете, что назначение константы 'double' или' long double' для чего-либо с большей точностью не сделает вас счастливыми, верно? Используйте 'l' suffic для' long double' и анализируем константу из строки, если вы проходите мимо 'long double'. – tmyklebu