PI и точность числа с плавающей точкой

Точное представление числа Пи с одинарной/двойной/расширенной точностью с точностью до десятичных знаков?

Ответ 1

#include <stdio.h>

#define E_PI 3.1415926535897932384626433832795028841971693993751058209749445923078164062

int main(int argc, char** argv)
{
    long double pild = E_PI;
    double pid = pild;
    float pif = pid;
    printf("%s\n%1.80f\n%1.80f\n%1.80Lf\n",
    "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899",
    pif, pid, pild);
    return 0;
}

Результаты:

[quassnoi #] gcc --version
gcc (GCC) 4.3.2 20081105 (Red Hat 4.3.2-7)

[quassnoi #] ./test

3.14159265358979323846264338327950288419716939937510582097494459230781640628620899

3.14159274101257324218750000000000000000000000000000000000000000000000000000000000
        ^
3.14159265358979311599796346854418516159057617187500000000000000000000000000000000
                 ^
3.14159265358979311599796346854418516159057617187500000000000000000000000000000000
                 ^
  0000000001111111
  1234567890123456

Ответ 2

Когда я изучал ответ Quassnoi, мне показалось подозрительным, что long double и double заканчиваются с одинаковой точностью, поэтому я немного покопался. Если я запускаю его код, скомпилированный с помощью clang, я получаю те же результаты, что и он. Однако я обнаружил, что если я указал long double суффикс и использовал литерал для инициализации long double суффикса, это обеспечило бы большую точность. Вот моя версия его кода:

#include <stdio.h>

int main(int argc, char** argv)
{
    long double pild = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899L;
    double pid = pild;
    float pif = pid;
    printf("%s\n%1.80f\n%1.80f\n%1.80Lf\n",
        "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899",
        pif, pid, pild);
    return 0;
}

И результаты:

3.14159265358979323846264338327950288419716939937510582097494459230781640628620899

3.14159274101257324218750000000000000000000000000000000000000000000000000000000000
        ^
3.14159265358979311599796346854418516159057617187500000000000000000000000000000000
                 ^
3.14159265358979323851280895940618620443274267017841339111328125000000000000000000
                    ^

Ответ 3

6 мест и 14 мест .1 место более 0 для 3, а последнее место, хотя и сохраненное, не может считаться точкой точности.

И извините, но я не знаю, что означает расширенные средства без дополнительного контекста. Вы имеете в виду С# decimal?

Ответ 4

Печать и подсчет, рождение ребенка, печать и подсчет. (Или прочитайте спецификации.)

Ответ 5

В модуле x86 с плавающей точкой (x87) есть инструкции для загрузки определенных констант с плавающей точкой. "fldz" и "fld1" загружают 0.0 и 1.0, например, на вершину стека "st" (иначе "st (0)"). Еще один "Fldpi".

Все эти значения имеют мантиссу длиной 64 бита, что означает почти 20 десятичных цифр. 64-битные значения возможны благодаря 80-битному временному формату с плавающей запятой, который используется внутри x87. X87 может загружать временные файлы и сохранять их в 10-байтовых ячейках памяти.

Ответ 6

Точность типа с плавающей запятой не связана с PI или какими-либо конкретными числами. Это зависит только от того, сколько цифр хранится в памяти для этого конкретного типа.

В случае IEEE-754 с float используется 23 бита мантиссы, поэтому он может иметь точность до 23 + 1 бит точности или ~ 7 цифр точности в десятичном формате. Независимо от π, e, 1.1, 9.87e9... все они хранятся с ровно 24 битами в float. Аналогично double (53 бита мантиссы) может хранить 15 ~ 17 десятичных цифр точности.

Ответ 7

Мир PI имеет PI до 100 000 000 000 цифр, вы можете просто распечатать и сравнить. Для немного более легкой для чтения версии Радость PI содержит 10 000 цифр. И если вы хотите запомнить цифры, вы можете попробовать прочесть стихотворение Cadaeic Cadenza.

Ответ 8

Для кода C просмотрите определения в <float.h>. Это охватывает определения float (FLT_*), double (DBL_*) и long double (LDBL_*).

Ответ 9

* РЕДАКТИРОВАТЬ: см. Этот пост для актуальной дискуссии: Реализация sinpi() и cospi() с использованием стандартной математической библиотеки C *

Новые функции math.h __sinpi() и __cospi() исправили проблему для прямых углов, таких как 90 градусов и тому подобное.

cos(M_PI * -90.0 / 180.0) returns 0.00000000000000006123233995736766
__cospi( -90.0 / 180.0 )      returns 0.0, as it should

/*  __sinpi(x) returns the sine of pi times x; __cospi(x) and __tanpi(x) return
the cosine and tangent, respectively.  These functions can produce a more
accurate answer than expressions of the form sin(M_PI * x) because they
avoid any loss of precision that results from rounding the result of the
multiplication M_PI * x.  They may also be significantly more efficient in
some cases because the argument reduction for these functions is easier
to compute.  Consult the man pages for edge case details.                 */
extern float __cospif(float) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);
extern double __cospi(double) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);
extern float __sinpif(float) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);
extern double __sinpi(double) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);
extern float __tanpif(float) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);
extern double __tanpi(double) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);

Ответ 10

Поскольку существуют ситовые уравнения для двоичных представлений pi, можно объединить переменные для хранения кусков значения для повышения точности. Единственным ограничением точности этого метода является преобразование из двоичного в десятичное, но даже рациональные числа могут столкнуться с проблемами с этим.