C中的Newton-Raphson

时间:2016-04-16 12:02:51

标签: c

我正在编写一个程序,使用C中的Newton-Raphson方法找到给定整数n的平方根的近似值。我使用了以下公式:

newton-raphson iteration

这是我的代码:

#include <stdio.h>

double newton_raphson(int n, int iter);

double newton_raphson(int n, int iter)
{
    if(iter == 0) // base case
        return 1;
    else // iterative case
        return (1/2*(newton_raphson(n, iter-1) + n/(newton_raphson(n, iter-1))));
}

int main()
{
    int n;
    int i;

    printf("Enter a number you want to know the square root of:\n");
    fflush(stdout);
    scanf("%d", &n);
    printf("Enter number of iterations to be worked out:\n");
    fflush(stdout);
    scanf("%d", &i);

    printf("%.3f", newton_raphson(n,i-1));

    return 0;
}

当我输入2和3时,预期输出为1.417(3次迭代后2的平方根)我得到错误-1。#IO。例如,当我输入5和2时,我得到0.000。我调试了它,但仍然无法弄清楚问题是什么。非常感谢任何帮助。

编辑:详细阐述了输出

1 个答案:

答案 0 :(得分:7)

您的问题似乎是您处理浮点算术错误。

  1. newton_raphson函数的第一个参数应该是double,特别是因为您似乎在递归地调用它。就像现在一样,您只需将一次迭代的结果转换为整数并将其传递给下一次迭代。

  2. 1 / 2使用整数运算。那应该是0.51.0 / 2.0。请注意,在整数运算中,1 / 20。您看到的错误是因为您将0传递给下一次迭代,然后它除以0

  3. 固定代码

    #include <stdio.h>
    
    double newton_raphson(double n, int iter);
    
    double newton_raphson(double n, int iter)
    {
        if (iter == 0) {
            return 1;
        }
        else {
            return 0.5 * (newton_raphson(n, iter - 1) + n/(newton_raphson(n, iter - 1)));
        }
    }
    
    int main()
    {
        int n;
        int i;
    
        printf("Enter a number you want to know the square root of:\n");
        fflush(stdout);
        scanf("%d", &n);
        printf("Enter number of iterations to be worked out:\n");
        fflush(stdout);
        scanf("%d", &i);
    
        printf("%.3f\n", newton_raphson(n, i - 1));
    
        return 0;
    }
    

    可能的改进

    正如其他人在评论中指出的那样,您可以提高此实施效率。

    首先,您可以通过将结果保存在变量中来消除函数调用。由于这是一个递归函数,如果你有很多次迭代,这将为你节省很多的执行时间。

    double newton_raphson(double n, int iter)
    {
        if (iter == 0) {
            return 1;
        }
        else {
            double xk = newton_raphson(n, iter - 1);
            return 0.5 * (xk + n / xk);
        }
    }
    

    然后,你可以完全消除递归。如果你运行多次迭代,这将使你的程序消耗更少的内存,因为你摆脱了不必要的堆栈操作。

    double newton_raphson(double n, int iter)
    {
        int k;
        double xk = 1;
        for (k = 0; k < iter; k++) {
            xk = 0.5 * (xk + n / xk);
        }
        return xk;
    }
    

    更多提示

    对于迭代计数,您应该使用unsigned int(或简称unsigned)而不是int。运行负数的迭代是没有意义的,例如。你无法运行-5次迭代......因此你不需要有符号整数。

    #include <stdio.h>
    
    double newton_raphson(double n, unsigned iter);
    
    double newton_raphson(double n, unsigned iter)
    {
        unsigned k;
        double xk = 1;
        for (k = 0; k < iter; k++) {
            xk = 0.5 * (xk + n / xk);
        }
        return xk;
    }
    
    int main()
    {
        int n;
        unsigned i;
    
        printf("Enter a number you want to know the square root of:\n");
        fflush(stdout);
        scanf("%d", &n);
        printf("Enter number of iterations to be worked out:\n");
        fflush(stdout);
        scanf("%u", &i);
    
        printf("%.3f\n", newton_raphson(n, i - 1));
    
        return 0;
    }
    

    更多的事情:

    • 通过检查函数的参数或可能返回零的函数调用结果,保护代码免受可能的零错误划分通常是一种很好的做法。
    • 您应该检查输入的负数,并告诉用户负数不是您可以使用此算法计算平方根的东西。
    • 对于输入,您可以允许用户输入浮点数而不是整数。