while(step > 0.02){
for(;;){
if(x+step <= 100.0 &&
(ttlen = ttl(x+step, y)) < minlength){
minlength = ttlen;
x += step;
} else if(x-step >=0.0 &&
(ttlen = ttl(x-step, y)) < minlength){
minlength = ttlen;
x -= step;
} else if(y+step <= 100.0 &&
(ttlen = ttl(x, y+step)) < minlength){
minlength = ttlen;
y += step;
} else if(y-step >= 0.0 &&
(ttlen = ttl(x, y-step)) < minlength){
minlength = ttlen;
y -= step;
} else break;
}
step /= 2.0;
}
在 x-y 平面上寻找一个对 ttl 函数的极值点。先用 step 为步长寻找,然后步长减半再找,直到满足一定精度为止。
逻辑上过程上都很简单才对,可惜以上代码在 VC2008 运行正确,用 Gcc 却陷入死循环。
调试下发现居然出现了这种情况:在 A 点时发现 B 比 A 小,然后在 B点 发现 C 比 B 小,而在 C点 又发现 A 更小……于是就在这几个点上跳不出来了。
其实以前也看过不少强调处理浮点数比较时要特别注意的地方,但每个地方都特别写一下又很麻烦,而且觉得 double 的精度够高应该不用担心,没想到还是出了问题。VC 里大概对浮点数的比较运算做了特殊处理才没出错,感觉在这种很细节的地方 VC 非常强调安全性,但可能有时候也会觉得多此一举或是担心性能上的影响吧。
总之发现问题所在就好解决了,(ttlen = ttl(x, y+step)) < minlength 改为 (ttlen = ttl(x, y+step)) < minlength - 1e-4 即可。
今后再处理浮点数的问题时一定要相当小心咯