我在这个话题上是个初学者,不知道原因:有时程序工作,有时不工作(问完问题,它根本不想接受我的答案,我想写多少就写多少,它不回答,只列出数字,我就喝了一杯)
#include <stdio.h>
float abszolut (float szam)
{
float abszoluterteke;
if (szam >=0)
abszoluterteke = szam;
else
abszoluterteke = -szam;
return abszoluterteke;
}
float negyzetgyok (float szam)
{
float pontossag = 0.000001;
float tipp = 1;
if (szam <0)
{
printf ("Megszakítás elfogadva! \nKöszönjük, hogy programunkat választotta!\n");
return -1;
}
else
{while (abszolut (tipp*tipp-szam) >= pontossag)
tipp = (szam/tipp + tipp)/2;
return tipp;
}
}
int main (void)
{
float alap, eredmeny;
for (;;)
{
printf ("Melyik számnak szeretnéd meghatározni a négyzetgyökét ilyen módszerrel?\n");
scanf ("%f", &alap);
eredmeny = negyzetgyok (alap);
if (eredmeny == -1)
return 1;
else
printf ("A(z) %f négyzetgyöke megfelelő közelítéssel: %f\n", alap, eredmeny);
}
return 0;
}
最佳答案
更改为abszolut (tipp*tipp-szam) >= pontossag*szam
当tipp*tipp
接近szam
时,while循环必须停止。但IEEE floating point computations的精度有限:约7位表示float
,15位表示double
。
所以float szam
上的错误大约是0.0000001*szam
。对于tipp
,也是一样的。因此,tipp*tipp-szam
上的误差大于0.0000001*szam
。如果szam
很大,则该误差几乎不会低于0.000001
。即使使用了double
精度,while (abszolut (tipp*tipp-szam) >= pontossag)
很可能会触发一个非常大的数的无限循环。
另一方面,如果szam
非常小,比如说1e-10
,会发生什么?while循环过早退出,1E-10的平方根被计算为关于1e-3
,而不是1e-5
…相对误差约为10000%。。。使用double
不会改变任何事情!
为了避免这种情况,您可以更改为abszolut (tipp*tipp-szam) >= pontossag*szam
。
注意两边都有相同的尺寸。如果szam
以平方英尺为单位,tipp
以英尺为单位,pontossag
的精度是无量纲的。比较具有相同维度的事物是一个很好的做法。
如果您一直注意到无限循环,请切换到双精度或增加pontossag
。
为了避免无限循环,如果计数器的迭代次数为100,则添加计数器int i;
并退出while循环。100应该足够了,因为Newton-Raphson iteration具有二次收敛性。
关于c - 牛顿拉夫森迭代陷入无限循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28781485/