PI и точность числа с плавающей точкой - PullRequest
11 голосов
/ 03 февраля 2009

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

Ответы [ 10 ]

23 голосов
/ 03 февраля 2009
#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
8 голосов
/ 28 марта 2014

Когда я изучал ответ Кассной, мне показалось подозрительным, что long double и double в итоге окажутся с одинаковой точностью, поэтому я немного покопался. Если я запускаю его код, скомпилированный с помощью clang, я получаю те же результаты, что и он. Однако я обнаружил, что если я указал суффикс 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 голосов
/ 03 февраля 2009

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

3 голосов
/ 03 февраля 2009

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

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

1 голос
/ 08 августа 2013

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

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

1 голос
/ 18 августа 2011

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

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

0 голосов
/ 15 марта 2016

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

0 голосов
/ 24 ноября 2015

* РЕДАКТИРОВАТЬ: см. Этот пост для актуального обсуждения: Реализация 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);
0 голосов
/ 04 февраля 2009

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

0 голосов
/ 03 февраля 2009

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

...