0
#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

Koustubh Jain
  • 129
  • 1
  • 7
  • 1
    `b*(guess, 2)` I guess should be `b * pow(guess, 2)`. Although `d + guess * (c + guess * (b + guess * a))` is probably a little better. – Paul Hankin Jan 22 '22 at 14:03
  • 1
    @KoustubhJain You should not compare floats like this. – wildplasser Jan 22 '22 at 14:06
  • @wildplasser could you please elaborate why ? – Koustubh Jain Jan 22 '22 at 14:07
  • You should never compare floats/doubles for equality. In your case, the value can get asymptotically *close ti zero*, but there is no guarantee that it will ever be *exactly* zero. (your `fabs(functional_value) <= accuracy)` -test does this correctly. – wildplasser Jan 22 '22 at 15:02
  • To prevent division by 0, you need to check after calculating `derivative` and before calculating `guess` – stark Jan 22 '22 at 15:08

1 Answers1

1

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.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thanks but I am using an IDE (CLion). Do you happen to know how I can change the warnings to errors in that ? It does show yellow caution highlights though – Koustubh Jain Jan 22 '22 at 14:07
  • "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" But I have used an "and" operator to make sure that the loop executes only when both the conditions are true, so then why will a division by zero occur ? – Koustubh Jain Jan 22 '22 at 14:11
  • 2
    @KoustubhJain: Sorry, I cannot help with your IDE. I do not use IDEs. I build software out of spare 0 and 1 bits harvested from the fragments at the ends of my disk files. – Eric Postpischil Jan 22 '22 at 14:11
  • 2
    @KoustubhJain: The program executes things in order. After `derivative = …;`, the next thing it executes is `guess -= ((functional_value)/(derivative)) ;`. After that, it evaluates the loop test. So, when the derivative is set to zero, the calculation of `guess` is performed before the loop test, and a division by zero is executed. – Eric Postpischil Jan 22 '22 at 14:42