0

I am writing a function in C with the below specifications:

float find_root(float a, float b, float c, float p, float q);

find_root takes the coefficients a,b,c of a quadratic equation and an interval (p, q). It will return the root of this equation in the given interval.

For example: find_root(1, -8, 15, 2, 4) should produce a root "close to" 3.0

I have written the below code, and I don't understand why it doesn't work:

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

main()
{
    printf("Hello World");
}

float find_root(float a, float b, float c, float p, float q) {

    float d,root1,root2;  
    d = b * b - 4 * a * c;
    root1 = ( -b + sqrt(d)) / (2* a);
    root2 = ( -b - sqrt(d)) / (2* a);

    if (root1<=q || root1>=p)
    {
        return root1;
    }
    return root2;
}

Please let me know what the error is.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
KLMM
  • 93
  • 1
  • 13
  • 2
    You should compile with all warnings & debug info (`gcc -Wall -Wextra -g`) then **use a debugger** (`gdb`) to run your code step by step. – Basile Starynkevitch Feb 06 '15 at 06:44
  • 3
    Please define `doesn't work`. Do you have a `main()`? Why not show us? Did you link with `-lm`? Why not tell us? – Sourav Ghosh Feb 06 '15 at 06:47
  • @BasileStarynkevitch Hi I tried that couldn't fix the bug. I wanted to confirm whether it is the debugger settings that I need to change or is there anything wrong with the code itself – KLMM Feb 06 '15 at 06:47
  • Using a debugger is a good way to understand how your program actually works. Of course, it won't correct your program magically. You need to think. If your program's behavior is not what you want, it means that there is a bug in your program. You have to investigate, then improve your source code. – Basile Starynkevitch Feb 06 '15 at 06:48
  • Actually the issue is this question was given as homework a while ago and in the course we are to use a specific debugger-compiler set called seashell. As a result I can't really change or view stuff. – KLMM Feb 06 '15 at 06:51

4 Answers4

2

Your program doesn't work, because, you never called find_root() from your main().

find_root() is not suppossed to run all-by-itself. Your program statrs execution from main(). You need to call your sub-function from main() in order to make them execute.

Change your main to have a call to find_root(), something like below.

int main()                              //put proper signature
{

float anser = 0;

answer = find_root(1, -8, 15, 2, 4);   //taken from the question
printf("The anser is %f\n", answer);        //end with a \n, stdout is line buffered

return 0;                                 //return some value, good practice

}

Then, compile the program like

gcc -o output yourfilename.c -lm

Apart from this, for the logical issue(s) in find_root() function, please follow the way suggested by Mr. @paxdiablo.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • I don't think having the main function is an issue as by default the compiler-debugger I am using adds a main function and a call, and hence if I add an main function its gonna throw out "duplicate function" error. – KLMM Feb 06 '15 at 06:58
  • The exact error I am facing is: Compile failed... see Public.compile.err for details /tmp/roots-KXflke.o: In function `find_root': /u/cs136t/49627.dir/roots.c:18: undefined reference to `sqrt' /u/cs136t/49627.dir/roots.c:19: undefined reference to `sqrt' clang: error: linker command failed with exit code 1 (use -v to see invocation) – KLMM Feb 06 '15 at 06:59
  • @L887: Sourav Ghosh wrote: *change* your `main`, not add a second one! – Basile Starynkevitch Feb 06 '15 at 06:59
  • @L887 See, that's the problem when you're not clear with your issue. – Sourav Ghosh Feb 06 '15 at 06:59
  • 1
    @L887 while compilation, you need to link with math library. See my updated answer.. – Sourav Ghosh Feb 06 '15 at 07:01
1

Your program starts at main by definition.

Your main function is not calling find_root but it should.

You need to compile with all warnings & debug info (gcc -Wall -Wextra -g) then use a debugger (gdb) to run your code step by step to understand the behavior of your program, so compile with

gcc -Wall -Wextra -g yoursource.c -lm -o yourbinary

or with

clang -Wall -Wextra -g yoursource.c -lm -o yourbinary

then learn how to use gdb (e.g. run gdb ./yourbinary ... and later ./yourbinary without a debugger)

Then you'll think and improve the source code and recompile it, and debug it again. And repeat that process till you are happy with your program.

BTW, you'll better end your printf format strings with \n or learn about fflush(3)

Don't forget to read the documentation of every function (like printf(3) ...) that you are calling.

You might want to give some arguments (thru your main(int argc, char**argv) ...) to your program. You could use atof(3) to convert them to a double

Read also about undefined behavior, which you should always avoid.

BTW, you can use any standard C compiler (and editor like emacs or gedit) for your homework, e.g. use gcc or clang on your Linux laptop (then use gdb ...). You don't need a specific seashell

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

For that data, your two roots are 5 and 3. With p == 2 and q == 4:

if (root1<=q || root1>=p)

becomes:

if (5<=4 || 5>=2)

which is true, so you'll get 5.

The if condition you want is:

if ((p <= root1) && (root1 <= q))

as shown in the following program, that produces the correct 3:

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

float find_root (float a, float b, float c, float p, float q) {
    float d,root1,root2;

    d = b * b - 4 * a * c;
    root1 = ( -b + sqrt(d)) / (2* a);
    root2 = ( -b - sqrt(d)) / (2* a);

    if ((p <= root1) && (root1 <= q))
        return root1;

    return root2;
}

int main (void) {
    printf ("%f\n", find_root(1, -8, 15, 2, 4));
    return 0;
}

That's the logic errors with your calculations of the roots.

Just keep in mind there are other issues with your code.

You need to ensure you actually call the function itself, your main as it stands does not.

It also wont produce a value within the p/q bounds, instead it will give you the first root if it's within those bounds, otherwise it'll give you the second root regardless of its value.

You may want to catch the situation where d is negative, since you don't want to take the square root of it:

a = 1000, b = 0, c = 1000: d <- -4,000,000

And, lastly, if your compiler is complaining about not being able to link sqrt (as per one of your comments), you'll probably find you can fix that by specifying the math library, something like:

gcc -o myprog myprog.c -lm
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

Change this condition

if (root1<=q || root1>=p)

to

if (root1<=q && root1>=p)

otherwise if anyone of the conditions is satisfied, root1 will be returned and root2 will almost never be returned. Hope this fixes your problem.

Arun A S
  • 6,421
  • 4
  • 29
  • 43