我发现了一个有趣的浮点问题。我必须在代码中计算几个平方根,表达式如下:
sqrt(1.0 - pow(pos,2))
其中 pos 循环从 -1.0 到 1.0。 -1.0 对于 pow 来说很好,但是当 pos=1.0 时,我得到一个 -nan。使用 gcc 4.4.5 和 icc 12.0 进行一些测试,输出为
1.0 - pow(pos,2) = -1.33226763e-15
and
1.0 - pow(1.0,2) = 0
or
poss = 1.0
1.0 - pow(poss,2) = 0
显然第一个会带来问题,是消极的。有人知道为什么 pow 返回一个小于 0 的数字吗?完整的违规代码如下:
int main() {
double n_max = 10;
double a = -1.0;
double b = 1.0;
int divisions = int(5 * n_max);
assert (!(b == a));
double interval = b - a;
double delta_theta = interval / divisions;
double delta_thetaover2 = delta_theta / 2.0;
double pos = a;
//for (int i = 0; i < divisions - 1; i++) {
for (int i = 0; i < divisions+1; i++) {
cout<<sqrt(1.0 - pow(pos, 2)) <<setw(20)<<pos<<endl;
if(isnan(sqrt(1.0 - pow(pos, 2)))){
cout<<"Danger Will Robinson!"<<endl;
cout<< sqrt(1.0 - pow(pos,2))<<endl;
cout<<"pos "<<setprecision(9)<<pos<<endl;
cout<<"pow(pos,2) "<<setprecision(9)<<pow(pos, 2)<<endl;
cout<<"delta_theta "<<delta_theta<<endl;
cout<<"1 - pow "<< 1.0 - pow(pos,2)<<endl;
double poss = 1.0;
cout<<"1- poss "<<1.0 - pow(poss,2)<<endl;
}
pos += delta_theta;
}
return 0;
}
当您在循环中不断增加 pos 时,舍入误差会累积,在您的情况下,最终值 > 1.0。相反,通过每轮乘法来计算 pos,以仅获得最小量的舍入误差。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)