PI和浮点数的准确性

问题描述 投票:11回答:10

Pi的单/双/扩展精度浮点表示精确到小数位数?

floating-point precision floating-accuracy
10个回答
24
投票
#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

0
投票

*编辑:请参阅此帖子以获取最新讨论:Implementation of sinpi() and cospi() using standard C math library *

新的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);

8
投票

当我检查Quassnoi的答案时,我似乎怀疑long doubledouble会以相同的准确度结束,所以我挖了一点。如果我运行他用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,最后一个地方虽然存储不能被视为精确点。

抱歉,但我不知道扩展意味着没有更多背景。你的意思是C#的小数?


3
投票

打印和计数,宝贝,打印和计数。 (或者阅读specs。)


1
投票

浮点类型的准确性与PI或任何特定数字无关。它仅取决于该特定类型在内存中存储的位数。

在IEEE-754的情况下,float使用23位尾数,因此精确到23 + 1位精度,或精确到十进制精度~7位。无论π,e,1.1,9.87e9 ......所有这些都以24位存储在一个浮点数中。类似地,double(53位尾数)可以存储15~17个十进制数字的精度。


1
投票

在x86浮点单元(x87)中,有一些加载某些浮点常数的指令。例如,“fldz”和“fld1”将0.0和1.0加载到堆栈顶部“st”(又名“st(0)”)上。另一个是“fldpi”。

所有这些值都有一个64位长的尾数,可转换成接近20位的十进制数字。通过x87内部使用的80位tempreal浮点格式,可以实现64位。 x87可以加载tempreals并将它们存储到10字节的内存位置。


0
投票

World of PI有PI到100,000,000,000个数字,你可以打印和比较。对于稍微容易阅读的版本,Joy of PI有10,000位数字。如果你想记住你自己的数字,你可以尝试学习Cadaeic Cadenza诗。


0
投票

对于C代码,请查看<float.h>中的定义。这涵盖了floatFLT_*),doubleDBL_*)和long doubleLDBL_*)的定义。


0
投票

由于存在用于pi的二进制表示的筛选方程,因此可以组合变量来存储该值的片段以提高精度。对这种方法的精度的唯一限制是从二进制到十进制的转换,但即使有理数也可能遇到问题。

© www.soinside.com 2019 - 2024. All rights reserved.