浮点数精度问题导致循环无法终止的技术求助
浮点数精度问题导致循环无法终止的技术求助
嘿,我来帮你捋捋这个循环停不下来的问题哈!
首先看你的需求:你想当两次迭代的数值变化小于小数点后14位(也就是差值小于1e-14)时让循环终止,但你的代码逻辑加上浮点数本身的精度特性,刚好让循环停不下来。
先说说你代码里的核心问题:
- 循环条件完全写反了!你用
stand_n - stand <= 10e-15作为循环继续的条件,意思是“只要两次值的差小于等于1e-14,就继续循环”——这和你想要的“差小于1e-14就停止”完全相反啊! - 另外,浮点数的比较最好用绝对值,虽然这个迭代是单调收敛到√2的,不会出现负差值,但养成这个习惯能避免很多潜在问题。
- 还有double类型的精度限制:double的有效位数大概是15-17位,当两个值的差小到double无法区分时,它们在内存里就是同一个值了,此时差值为0,你的条件会一直满足,循环就无限跑下去了。
再看你的输出,当数值收敛到1.41421356237309之后就不再变化了,这是因为double已经没法表示更精确的数值了,此时stand_n和stand完全相等,差值为0,你的循环条件0 <= 1e-14永远成立,自然停不下来。
给你改了一份代码,你试试:
#include <stdio.h> #include <math.h> int main (void) { double stand = 1.0; // 先算出第一个迭代值 double stand_n = 1.0 / stand + stand / 2.0; printf("%.14lf\n", stand_n); // 当两次值的差的绝对值大于1e-14时,继续迭代 while (fabs(stand_n - stand) > 1e-14) { // 把当前值赋值给旧值 stand = stand_n; // 计算新的迭代值 stand_n = 1.0 / stand + stand / 2.0; printf("%.14lf\n", stand_n); } }
这个代码的逻辑是:先计算第一个新值,然后每次判断当前值和上一次值的差,如果差还足够大(大于1e-14),就继续迭代;当差小到阈值以下时,直接退出循环,完美符合你的需求。
备注:内容来源于stack exchange,提问作者Tasos Charto




