Search code examples
cnewtons-method

Why does this code for newton's method not work in C (using a while loop)?


#include <stdio.h>
#include <math.h>

int main()
{
    // ax^3 + bx^2 + cx + d = 0
    float a,b,c,d,guess,derivative;
    double functional_value, accuracy;

    printf("Please enter values for a,b,c,d respectively :\n");
    scanf("%f %f %f %f", &a, &b, &c, &d);

    printf("Please enter your best guess for a root:\n");
    scanf("%f", &guess);

    printf("How close you want the value to be ?\n");
    scanf("%f", &accuracy);

    while (fabs(functional_value) <= accuracy && derivative != 0)
    {
        functional_value = a*pow(guess,3) + b*pow(guess,2) + c*(guess) + d ;
        // 3ax^2 + 2bx + c
        derivative = 3*a* pow(guess,2) + 2*b*(guess) + c ;
        guess -= ((functional_value)/(derivative)) ;
    }

    printf("A root of the equation is approximately equal to %f", guess);

    return 0;
}

I am new to programming, I was just learning C in college. And I wanted to make a program that would calculate roots using newton's method for up to cubic polynomials. So I wrote the above code.

But when I run it, the loop seems to run infinitely. I even tried giving the inputs as 0 1 -2 1 (a quadratic equation whose root is 1) but the loop is still running.

I don't notice any mistakes. Can anyone please help me in finding my mistake ? like what's wrong ?

At first I didn't have any parameter for the accuracy i.e. how close one would want the root to be, so I added that as a double.

I have looked at somewhat similar questions but I don't know all the things in C they are using.

Edit#1 : Thanks for the comments and pointing out my foolish syntax mistakes

Edit#2 : Now the program runs but it doesn't calculate a root still. I get the following output

Please enter values for a,b,c,d respectively :
0 1 -2 1
Please enter your best guess for a root:
0.5
How close you want the value to be ?
0.01
A root of the equation is approximately equal to nan
Process finished with exit code 0

Edit#3 : Thanks to Eric Postpichilli now the program does calculate a root after using fabs() and comparing the functional_value to be less than or equal to accuracy. But I still can't understand why will a division by zero occur, I have used an "AND" operator in the loop condition to try and prevent that


Solution

  • Compiling with warnings enabled (using Clang) reveals:

    • In line 17, scanf("%f", &accuracy); is wrong because %f is for scanning a float, but accuracy is a double.
    • In line 48, the compiler reports the guess of b*(guess,2) is unused. This is because the intended pow is missing, so guess,2 forms a comma-operator expression, which ignores its left operand.
    • In line 19, while (functional_value != accuracy & derivative != 0), functional_value and derivative are used without having been initialized.

    Always compile with warnings enabled. With Clang, start with -Wmost. With GCC, start with -Wall. With MSVC, start with /W3.

    Elevate warnings to errors. With Clang and GCC, use -Werror. With MSVC, use /WX.

    You may want to make the loop a do … while instead of a while … so that functional_value is given a value before being used. However, the loop test is still wrong. There is no reason to expect functional_value will ever exactly equal accuracy. You want some test of whether functional_value is at least as close as accuracy, such as fabs(functional_value) <= accuracy.

    Also, by the time derivative != 0 is tested in the loop test, it is too late, because it was already used in (functional_value)/derivative, so a division by zero will have been executed.