Jos*_*ley 5 c math floating-point trigonometry rounding
我正在用C/C++进行一些三角计算,并且遇到了舍入错误的问题.例如,在我的Linux系统上:
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
printf("%e\n", sin(M_PI));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序提供以下输出:
1.224647e-16
Run Code Online (Sandbox Code Playgroud)
当正确的答案当然是0.
使用trig函数时,我可以期待多少舍入误差?我怎样才能最好地处理这个错误?我熟悉用于比较浮点数的最后位置单位技术,来自Bruce Dawson的比较浮点数,但这似乎在这里不起作用,因为0和1.22e-16相当于几个ULP.
Mar*_*ett 14
对于罪(pi),答案只有0 - 你是否包括Pi的所有数字?
- 有没有人注意到这里明显缺乏,讽刺/幽默感?
And*_*oss 13
IEEE双重存储52位尾数,"隐式前导"形成53位数.因此,结果的最低位中的错误占数字比例的约1/2 ^ 53.您的输出与1.0的顺序相同,因此几乎只有10 ^ 16中的一个部分(因为53*log(2)/ log(10)== 15.9).
是的 这大约是您可以预期的精度限制.我不确定您使用的ULP技术是什么,但我怀疑您的应用是错误的.
@Josh Kelley - 好的回答.
通常,您不应该将涉及浮点数或双精度数的任何操作的结果相互比较.
唯一的例外是分配.
浮动a = 10.0;
float b = 10.0;
那么a == b
否则你总是要编写一些函数,比如bool IsClose(float a,float b,float error),以便检查两个数字是否在彼此的"错误"范围内.
记得还要检查标志/使用晶圆厂 - 你可能有-1.224647e-16
π的正弦是0.0.
正弦M_PI值约为1.224647e-16.
M_PI 不是π.
程序给出... 1.224647e-16当正确的答案当然是0.
Code给出了7个地方的正确答案.
以下不打印π的正弦.它打印的数字正弦接近π.见下图.
? // 3.1415926535897932384626433832795...
printf("%.21\n", M_PI); // 3.141592653589793115998
printf("%.21f\n", sin(M_PI));// 0.000000000000000122465
Run Code Online (Sandbox Code Playgroud)
注意:使用数学函数sine(x),在x =π时曲线的斜率为-1.0 .π的差异M_PI与sin(M_PI)- 正如预期的那样.
我遇到了舍入错误的问题
当M_PI用于呈现π 时发生舍入问题 . M_PI是double最接近π,但由于π是无理的,所有有限double都是理性的,它们必须不同 - 即使是少量.所以不是直接的舍入问题sin(), cos(), tan(). sin(M_PI)简单暴露问题始于使用不精确的π.
sin(M_PI)如果代码使用不同的FP类型float,long double或者double使用除53位二进制精度之外的其他东西,则会出现此问题,并且会出现不同的非零结果.这不是一个精确的问题,而是一个非理性/理性问题.