牛顿拉夫森迭代陷入无限循环 [英] Newton Raphson iteration trapped in infinite loop

查看:197
本文介绍了牛顿拉夫森迭代陷入无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是这个主题的初学者,无法找出原因:有时程序可以工作,有时不能(在问了问题之后,它根本不想接受我的答案,我可以尽可能多地写下来,但它没有响应,只列出我输入的数字)

I'm quite a beginner in this topic, and couldn't find out the reason: sometimes the program works, sometimes not (after asking the question, it simply doensn't want to take in my answers, than I can write in as much as I want, it doesn't respond, just list out the numbers, I tiped in)

  #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;
}

推荐答案

您的代码存在许多问题.

There are a number of problems with your code.

循环中的退出条件有缺陷.
平方根算法的问题是使用了错误限制pontossag.对于非常小的数字,您的算法将给出错误的结果,并且对于大于20左右的数字,它将永远循环.要解决此问题,请将循环测试从abszolut (tipp*tipp-szam) >= pontossag更改为abszolut (tipp*tipp-szam) >= pontossag*szam.

The exit condition in your loop is flawed.
The problem with your square root algorithm is the use of the error limit pontossag. Your algorithm will give erroneous results for very small numbers and it will loop forever for numbers larger than 20 or so. To fix this, change the loop test from abszolut (tipp*tipp-szam) >= pontossag to abszolut (tipp*tipp-szam) >= pontossag*szam.

您并没有检查所有有问题的情况.
如果您的计算机使用IEEE 754浮点,则您的算法可以正常工作.真是运气.进行数值编程时,切勿依赖运气.输入无穷大很容易.例如,3.5e38(350000000000000000000000000000000000000000000)使用单精度数字(float)来完成技巧.您的函数negyzetgyok应该检查无穷大:

You aren't checking for all the problem cases.
If your computer uses IEEE 754 floating point, your algorithm happens to work. That's just luck. Never rely on luck when doing numerical programming. It's easy to input an infinity. For example, 3.5e38 (350000000000000000000000000000000000000) does the trick with single precision numbers (float). Your function negyzetgyok should check for infinity:

if (isinf (szam))
{
    return szam;
}

与做一个平方根的初始猜测值1.0相比,您可以做的更好.
相对于3.4e38的1.0的初始猜测意味着很多不必要的循环.形成良好的初始猜测的一种快速简便的方法是利用以下事实:浮点数在内部表示为(1+fractional_part)*2^exponent.一个很好的第一个猜测是1*2^(exponent/2).使用单精度数字,

You can do much better than an initial guess of 1.0 as the square root.
An initial guess of 1.0 against 3.4e38 means a lot of needless looping. A fast and easy way to form a good initial guess is to take advantage of the fact that floating point numbers are represented internally as (1+fractional_part)*2^exponent. A good first guess is 1*2^(exponent/2). With single precision numbers,

int expo;
float tipp;
frexpf (szam, &expo);
tipp = ldexpf (1.0f, n/2);

您正在使用%f而不是%g来解析浮点数.
%g格式可以解析可以用%f格式解析的任何内容,以及更多.

You are using %f rather than %g to parse floating point numbers.
The %g format can parse anything that can be parsed with the %f format, plus a whole lot more.

您没有检查fscanf的状态. 当提示您输入数字时,输入x.扫描仪将读取该字符,这将停止扫描.扫描程序将把该字符(x)放回输入缓冲区,并返回0,表示未扫描任何内容.下次,扫描程序将再次读取字符x,再次将该字符放回输入缓冲区,然后再次返回0.无限循环!始终检查scanf系列任何功能的状态,以查看扫描仪是否扫描了预期的项目数量.

You aren't checking the status of fscanf. Enter x when prompted to enter a number. The scanner will read that character, which stops the scan. The scanner will put that character (x) back into the input buffer, and return 0, indicating that nothing was scanned. The next time around, the scanner will read the character x again, once again put that character back into the input buffer, and once again return 0. Infinite loop! Always check the status of any of the scanf family of functions to see if the scanner scanned the number of items expected.

您正在使用fscanf.
此站点上存在许多现有的问题和解答,这些问题和答案解决了使用fscanf读取文件的许多问题.读取人工生成的输入时尤其如此.人们会犯错误.忽略人们在输入数据时确实犯了错误是编程错误.更好的方法是使用frets将行读入缓冲区,并使用sscanf解析该行.

You are using fscanf.
There are a number of existing questions and answers at this site that address the many problems with using fscanf to read from a file. This is particularly so when reading human-generated input. People make mistakes. Ignoring that people do make mistakes on entering data is a programming error. A better approach would be to read a line into a buffer using frets and parse that line with sscanf.

这篇关于牛顿拉夫森迭代陷入无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆