/* * Find real roots of quadratic equation: * Prompt for coefficients. * Print roots if they exist, else message. Also do simple checking * that input is okay. * * This version packages the code to solve and print results in * yet another way, with one function to do the solving and other * functions to print results, run tests/examples, etc. * It's probably too much for such a simple calculation but does * illustrate use of functions, pointer parameters, etc. * * Compile with -lm for sqrt. */ #include #include /* * flag indicating that all coefficients are zero and so all values of x * are solutions. * (this is admittedly a pathological case but if we want to be thorough .... */ #define COEFFICIENTS_ALL_ZERO -1 /* * function to compute roots of a*x*x + b*x + c = 0. * returns number of real roots, or special value if all coefficients are zero. */ int quadratic(double a, double b, double c, double *root1, double *root2); /* * function to print results of quadratic(). */ void print_results(int nroots, double r1, double r2); /* * function to test other functions. * first three parameters are coefficients for equations, other parameters * are expected results. * must have expected_r1 >= expected_r2 if both are used */ void test(double a, double b, double c, int expected_nroots, double expected_r1, double expected_r2); /* main function */ int main(void) { printf("program to solve a*x*x + b*x + c = 0\n"); printf("examples/tests:\n\n"); /* tests/examples that try to cover all the different possibilities */ /* * notice that we have to supply values for all parameters even though * for some cases the values for the last two (expected roots) are not * used. */ /* 2*x*x - 8 = 0 (two roots) */ test(2.0, 0.0, -8.0, 2, 2.0, -2.0); /* (2x+1)*(x+5) = 0 (two roots) */ test(2.0, 11.0, 5.0, 2, -0.5, -5.0); /* (5x+1)*(x+5) = 0 (two roots) */ test(5.0, 26.0, 5.0, 2, -0.2, -5.0); /* 1*x*x = 0 (one root) */ test(1.0, 0.0, 0.0, 1, 0.0, 0.0); /* 1*x*x + 2 = 0 (no roots) */ test(1.0, 0.0, 2.0, 0, 0.0, 0.0); /* 2*x - 5 = 0 (linear, one root) */ test(0.0, 2.0, 5.0, 1, -2.5, 0.0); /* 5 = 0 (does this have a name? no roots) */ test(0.0, 0.0, 5.0, 0, 0.0, 0.0); /* 0 = 0 (does this have a name? all roots) */ test(0.0, 0.0, 0.0, COEFFICIENTS_ALL_ZERO, 0.0, 0.0); double a, b, c; printf("enter coefficients a, b, c (floating-point)\n"); if (scanf("%lf %lf %lf", &a, &b, &c) != 3) { printf("error: non-numeric input\n"); return 1; } printf("input %f %f %f\n", a, b, c); double root1, root2; int num_roots = quadratic(a, b, c, &root1, &root2); print_results(num_roots, root1, root2); return 0; } int quadratic(double a, double b, double c, double *root1, double *root2) { /* check for cases where the formula does not work */ if (a == 0) { if (b == 0) { if (c == 0) { /* special value for this case */ return COEFFICIENTS_ALL_ZERO; } else { return 0; } } else { *root1 = -c/b; return 1; } } else { /* compute discrim and test for < 0 (no roots) */ double discrim = b*b - 4*a*c; if (discrim < 0) { /* no real roots */ return 0; } else if (discrim == 0) { /* one root */ *root1 = -b / (2*a); return 1; } else { /* two roots */ *root1 = (-b + sqrt(discrim)) / (2*a); *root2 = (-b - sqrt(discrim)) / (2*a); return 2; } } } void print_results(int nroots, double r1, double r2) { switch (nroots) { case COEFFICIENTS_ALL_ZERO: printf("coefficients all zero, so everything is a root\n"); break; case 0: printf("no real roots\n"); break; case 1: printf("one real root %f\n", r1); break; case 2: printf("two real roots %f, %f\n", r1, r2); break; default: /* should not happen unless bug in quadratic() */ /* FIXME so maybe do something else here?? */ printf("unexpected return value %d from quadratic()\n", nroots); } } /* returns 0 on success, something else on failure */ int check_results(int expected_nroots, double expected_r1, double expected_r2, int nroots, double r1, double r2) { if (nroots != expected_nroots) return 1; else if (nroots == COEFFICIENTS_ALL_ZERO) return 0; else if (nroots == 0) return 0; else if ((nroots == 1) && (r1 == expected_r1)) return 0; else if ((nroots == 2) && (r1 == expected_r1) && (r2 == expected_r2)) return 0; else return 1; } void test(double a, double b, double c, int expected_nroots, double expected_r1, double expected_r2) { printf("testing with %f %f %f\n", a, b, c); /* first get function results and print */ double r1, r2; int nroots = quadratic(a, b, c, &r1, &r2); print_results(nroots, r1, r2); /* FIXME compare results to expected results -- to finish in class? */ if (check_results(expected_nroots, expected_r1, expected_r2, nroots, r1, r2) == 0) { puts("results match expected values"); } else { puts("results do not match expected values:"); print_results(expected_nroots, expected_r1, expected_r2); } puts(""); }