我是这个主题的初学者,并且找不到原因:有时程序有效,有时候没有(在提出问题之后,它根本不想接受我的答案,而不是我可以写作我想要它,它没有回应,只列出数字,我插入)
#include 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 = 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: %fn", alap, eredmeny); } return 0; }
更改为abszolut (tipp*tipp-szam) >= pontossag*szam
一旦tipp*tipp
接近szam
,while循环必须停止。 但IEEE浮点计算的精度有限: float
大约为7位, double
精度位数为15位。
所以float szam
的错误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
。
为了避免无限循环,添加一个计数器int i;
如果迭代次数为100,则退出while循环.100应该足够了,因为Newton-Raphson迭代具有二次收敛。
您的代码存在许多问题。
循环中的退出条件存在缺陷。
平方根算法的问题是使用误差限制pontossag。 您的算法将为非常小的数字提供错误的结果,并且对于大于20的数字,它将永远循环。 要解决此问题,请将循环测试从abszolut (tipp*tipp-szam) >= pontossag
为abszolut (tipp*tipp-szam) >= pontossag*szam
。
您没有检查所有问题情况。
如果您的计算机使用IEEE 754浮点,您的算法就会起作用。 那只是运气。 在进行数值编程时,不要依赖运气。 输入无穷大很容易。 例如,3.5e38(350000000000000000000000000000000000000)可以使用单精度数字( float
)。 你的函数negyzetgyok
应检查无穷大:
if (isinf (szam)) { return szam; }
你可以比平方根的初始猜测1.0做得更好。
初始猜测1.0对3.4e38意味着很多不必要的循环。 形成良好初始猜测的快速简便方法是利用浮点数在内部表示为(1+fractional_part)*2^exponent
的事实。 一个好的第一个猜测是1*2^(exponent/2)
。 使用单精度数字,
int expo; float tipp; frexpf (szam, &expo); tipp = ldexpf (1.0f, n/2);
您使用%f
而不是%g
来解析浮点数。
%g格式可以解析任何可以使用%f格式解析的内容,还有更多内容。
您没有检查fscanf
的状态。 提示输入数字时输入x
。 扫描仪将读取该字符,从而停止扫描。 扫描仪将该字符( x
)放回输入缓冲区,并返回0,表示没有扫描任何内容。 下一次,扫描仪将再次读取字符x
,再次将该字符放回输入缓冲区,再次返回0.无限循环! 始终检查任何scanf
系列function的状态,以查看扫描仪是否扫描了预期的项目数。
您正在使用fscanf
。
这个站点有许多现有的问题和答案,解决了使用fscanf
从文件中读取的许多问题。 在阅读人为输入时尤其如此。 人们犯错误。 忽略人们确实在输入数据时出错是编程错误。 更好的方法是使用frets
将行读入缓冲区并使用sscanf
解析该行。
以上就是c/c++开发分享Newton Raphson迭代陷入无限循环相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/523140.html