Pi的单/双/扩展精度浮点表示精确到小数位数?
#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
*编辑:请参阅此帖子以获取最新讨论: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);
当我检查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
^
6个地方和14个地方.1个地方超过0,最后一个地方虽然存储不能被视为精确点。
抱歉,但我不知道扩展意味着没有更多背景。你的意思是C#的小数?
打印和计数,宝贝,打印和计数。 (或者阅读specs。)
浮点类型的准确性与PI或任何特定数字无关。它仅取决于该特定类型在内存中存储的位数。
在IEEE-754的情况下,float
使用23位尾数,因此精确到23 + 1位精度,或精确到十进制精度~7位。无论π,e,1.1,9.87e9 ......所有这些都以24位存储在一个浮点数中。类似地,double
(53位尾数)可以存储15~17个十进制数字的精度。
在x86浮点单元(x87)中,有一些加载某些浮点常数的指令。例如,“fldz”和“fld1”将0.0和1.0加载到堆栈顶部“st”(又名“st(0)”)上。另一个是“fldpi”。
所有这些值都有一个64位长的尾数,可转换成接近20位的十进制数字。通过x87内部使用的80位tempreal浮点格式,可以实现64位。 x87可以加载tempreals并将它们存储到10字节的内存位置。
World of PI有PI到100,000,000,000个数字,你可以打印和比较。对于稍微容易阅读的版本,Joy of PI有10,000位数字。如果你想记住你自己的数字,你可以尝试学习Cadaeic Cadenza诗。
对于C代码,请查看<float.h>
中的定义。这涵盖了float
(FLT_*
),double
(DBL_*
)和long double
(LDBL_*
)的定义。
由于存在用于pi的二进制表示的筛选方程,因此可以组合变量来存储该值的片段以提高精度。对这种方法的精度的唯一限制是从二进制到十进制的转换,但即使有理数也可能遇到问题。