I am trying to write a program to find roots of a continuous function using False Position Method. But, I am getting the same value of c again and again and same value is assigned to a, resulting in reaching the limit of MAX_ITER. How should I avoid this ? Am I not using the algorithm correctly ?
#include<stdio.h>
#include<math.h>
#define F(x) ((2*x)+1)
#define ERROR 0.00001
#define MAX_ITER 1000
float FalsePosition(float a, float b)
{
float c;
int iter = 0;
do
{
c = (b - F(b)) * (b - a) / (F(b) - F(a));
printf("F(a): %f, F(b) : %f, F(c) : %f, a: %f, b : %f, c : %f\n", F(a), F(b), F(c), a, b, c);
if((F(c) > 0 && F(a) > 0) || (F(c) < 0 && F(a) < 0))
{
a = c;
}
else
{
b=c;
}
iter++;
}
while(fabsf(a-b) > ERROR && iter < MAX_ITER);
return a;
}
int main()
{
float a = -2.5;
float b = 2.5;
printf("Finding root in the interval [%f, %f]\n", a, b);
if((F(a)>0 && F(b)>0) || (F(a)<0 && F(b)<0))
{
printf("No root lie in the interval [%f, %f]", a, b);
}
else
{
printf("The root is : %f\n", FalsePosition(a, b));
}
return 0;
}
Your formula for c is wrong, it should be
c = b - (f(b) * (b - a)) / (f(b) - f(a));
see here
To prevent reaching MAX_ITER iterations, you may want to watch the change in c something like
previousValue = c;
c = b - (f(b) * (b - a)) / (f(b) - f(a));
and then, the while condition would be
while ((fabs(previousValue - c) > ERROR) && (iter < MAX_ITER));
you can initialize previousValue to a befor beginig the loop.
And finally you should return c not a.
Related
I wrote code of determining if three edges (input) can form a triangle, but when the input is "1.1 2.2 3.3", there's a problem. Here's my code:
#include <stdio.h>
#include <math.h>
int main() {
float a, b, c;
float s, area;
scanf("%f %f %f", &a, &b, &c);
if (a > 0 && b > 0 && c > 0) {
if (a + b > c && b + c > a && a + c > b) {
s = (a + b + c) / 2;
area = sqrt(s * (s - a) * (s - b) * (s - c));
printf("%f", area);
} else
printf("error input");
} else {
printf("error input");
}
}
When I enter "1.1 2.2 3.3", the output is "0.001380", but it's supposed to be "error input" because 1.1+2.2==3.3. Besides, when I enter other floats like "2.2 3.3 5.5", the output is "error input". Could someone please explain why?
If you run debugger, you can see a+b==3.30000019 and c==3.29999995 so it's limited precision problem.
You can avoid this by using double type or use epsilon like below
#include <stdio.h>
#include <math.h>
int main() {
float a, b, c;
float s, area;
scanf("%f %f %f", &a, &b, &c);
if (a > 0 && b > 0 && c > 0) {
float eps = 1e-5;
if (fabsf(a + b - c) < eps || fabsf(b + c - a) < eps || fabsf(a + c - b) < eps) {
printf("error input");
}
else {
s = (a + b + c) / 2;
area = sqrt(s * (s - a) * (s - b) * (s - c));
printf("%f", area);
}
}
else {
printf("error input");
}
}
I was given a problem to write a C program which would solve the equation ax2+bx+c=0, where a, b and c are coefficients with double type. Any of the coefficients may be zero. In this problem it is unclear to me how to handle the double variables.
Here is my code. As for now, I know that my program can't distinguish between two roots and infinitely many roots. It also doesn't detect the "linear equation situation". How can I make it detect an infinite number of solutions? I was also advised in the comments to calculate the root with the minus before the discriminant if b > 0 and then use the Viet's theorem. I understand that it is because it is always more accurate to sum two numbers. I also guess I should do the exact opposite with b < 0. But what if b == 0 ? In this case, the program will not do anything. Or should I just include b == 0 in b < 0 and have b <= 0 ?
#include <stdio.h>
#include <math.h>
#include <float.h>
int main() {
double a, b, c, x1, x2;
scanf("%lf", &a);
scanf("%lf", &b);
scanf("%lf", &c); // just reading variables
//ax^2+bx+c=0
if ((b * b - 4 * a * c) < 0) {
printf("no");
} else {
x1 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a); //calculating roots
x2 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a);
if ((fabs((a * x1 * x1 + b * x1 + c)) < DBL_EPSILON) & (fabs((a * x2 * x2 + b * x2 + c)) < DBL_EPSILON)) { //plugging the roots in
if (fabs((x1 - x2)) < DBL_EPSILON) { //checking if the roots are equal
printf("%lf", &x1); // if they are equal, we print only one of them
} else {
printf("%lf", &x1); // if they are not equal, we print both.
printf("\n %lf", &x2);
}
} else { // if there are no two valid roots
if ((fabs((a * x1 * x1 + b * x1 + c)) < DBL_EPSILON)) // we try to find one root.
printf("%lf", &x1);
if (fabs((a * x2 * x2 + b * x2 + c)) < DBL_EPSILON)
printf("%lf", &x2);
if ((fabs((a * x1 * x1 + b * x1 + c)) > DBL_EPSILON) & (fabs((a * x2 * x2 + b * x2 + c)) > DBL_EPSILON)) // if both of the plugged roots don't satisfy the equation
printf("no");
}
}
return 0;
}
Solve quadratic equation when coefficients may be 0
How can I make it detect an infinite number of solutions?
When a==0 && b == 0 && c == 0.
No DBL_EPSILON needed really anywhere in this code. See also #Eric Postpischil.
But what if b == 0 ?
if (b == 0) { // y = a*x*x + c
if (a) {
double dd = -c/a;
if (dd >= 0) {
double d = sqrt(d);
printf_roots("+/- roots", d,-d);
} else {
printf_roots("Complex roots", NAN, NAN); // Note NAN may not exist
}
} else if (c) { // y = 0*x*x + c, c != 0
printf_roots("No roots", NAN, NAN);
} else { // y = 0*x + 0
printf_roots("Infinite roots", -HUGE_VAL, HUGE_VAL);
}
Or should I just include b == 0 in b < 0 and have b <= 0 ?
Unless the coding goal requires a special output when b==0, I would only vector code on b==0 as a subtest when a==0 occurred.
if (a==0) {
if (b == 0) {
The quadric equation, like much FP code, can readily overflow and hit 0, both cases losing all precision.
Consider the code below: the unnecessary subtraction may cause overflow or truncation to 0 versus the second which may not. It is dependent on many things.
if ((b * b - 4 * a * c) < 0)
//
if (b * b < 4 * a * c)
Further, C allows various calculations to occur using wider math. Research FLT_EVAL_METHOD. Because of this, to prevent sqrt(value_less_than_0), code should calculate the discriminate and then test the object x that is going to be applied to sqrt(x).
//if ((b * b - 4 * a * c) < 0) {
// printf("no");
//} else {
// x1 = (-b + sqrt(b * b - 4 * a * c))
double discriminate = b * b - 4 * a * c;
if (discriminate < 0) {
printf("no");
} else {
double d = sqrt(discriminate);
x1 = (-b + d)
As to the idea of "calculate the root with the minus before the discriminant if b > 0 and then use the Viet's theorem", I'd suggest for improved retained precision the below which does not subtract like signed values.
double d = sqrt(discriminate);
// Note x1*x2 = c/a
if (b < 0) {
x2 = (-b + d)/(2*a);
x1 = c/a/x2;
} else {
x1 = (-b - d)/(2*a);
x2 = c/a/x1;
}
printf_roots("2 roots", x1, x2);
Notes on printf("%lf", &x1);. You are not compiling with all warnings enabled. Save time - enable them. Should be printf("%lf", x1); No &.
Further double is floating point. For FP code development use "%e", "%a" or"%g" to full see significant information.
printf("%g\n", some_double);
// or better
printf("%.*e\n", DBL_DECIMAL_DIG -1, some_double);
Since division by zero is not allowed, you have to split the problem into 4 cases :
a != 0:
this is case you treated in your code.
a == 0 && b != 0 :
This is a linear equation where the solution is x = -c/b
a == 0 && b == 0 && c != 0 : There's no possible value for x.
In this last case, a, b and c are equals to 0 : there's infinitly many solutions for x.
EDIT: comparisons with epsilon removed since they seem to be useless
There are some problems in your code:
you should check the return values of scanf() to avoid undefined behavior on invalid input.
you should use local variables for intermediary results to improve code readability
your printf statements are incorrect: you should pass the values of the double variables instead of their addresses: printf("%lf", &x1); should read:
printf("%f", x1);
Regarding the degenerate cases, you should just test those before trying to resolve the second degree equation.
Here is a corrected version:
#include <stdio.h>
#include <math.h>
int main() {
double a, b, c, delta, x1, x2;
if (scanf("%lf%lf%lf", &a, &b, &c) != 3) {
printf("invalid input\n");
return 1;
}
if (a == 0) {
// not a quadratic equation
if (b != 0) {
printf("one solution: %g\n", -c / b);
} else {
if (c != 0) {
printf("no solution\n");
} else {
printf("all real values are solutions\n");
}
}
} else {
delta = b * b - 4 * a * c;
if (delta < 0) {
printf("no real solution\n");
} else
if (delta == 0) {
printf("one double solution: %g\n", -b / (2 * a));
} else {
x1 = (-b + sqrt(delta)) / (2 * a);
x2 = (-b - sqrt(delta)) / (2 * a);
printf("two solutions: %g, %g\n", x1, x2);
}
}
return 0;
}
I am trying to write a program that will find all acute triangle solutions after the user enters a min and max value (dmin and dmax). Right now I think I have the program working using only for() loops, but I need to change the first for() loop to a do{}while loop, which is confusing me. I'm not able to figure out how to write the do{}while loop so that is also includes these nested for() loops and the if statements. Everything I've tried either tells me b and c aren't being used or it just runs and provides no output. Here is my code with the for() loops.
double a = 0, b = 0, c = 0;
printf("Here are the acute triangle solutions the program found:\n");
for (c = dmin; c <= dmax, c++)
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; a++)
{
if (a * a + b * b - c == c * c ){ //
if (((a + b) > c) && ((b + c) > a) && ((b + a) > b))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
}
a for (e1;e2;e3) something loop can be transformed in:
e1;
while (e2) {
something;
e3;
}
or:
e1;
if (e2) {
do {
something;
e3;
} while (e2);
}
In a do while, you simply do an initialization before and the check after. It is really somewhat similar to what the system does for a for loop.
The following code:
for (c = dmin; c <= dmax, c++)
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; a++)
{
if (a * a + b * b - c == c * c ){ //
if (((a + b) > c) && ((b + c) > a) && ((c + a) > c))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
}
Becomes:
c = dmin;
if(c < dmax) { //Make sure not to run once if c is greater
do
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; a++)
{
if (a * a + b * b - c == c * c ){ //
if (((a + b) > c) && ((b + c) > a) && ((c + a) > b))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
} while( ++c <= dmax );
}
I wrote this program to give the user all acute triangle solutions when they give a min and max value. It works correctly except it seems like the solutions don't include the first iterations of the loops (for example, with min = 1 and max = 45, (1, 1, 1) isn't included in the solutions). How can this be fixed? I thought the problem was with my while-loop for the a-value, but when I changed it into a for-loop, the problem persisted. How can I have it include these first values?
if (c >= dmin) {
c = dmin;
do {
++c;
for (b = dmin; b < dmax; b++) {
a = dmin;
while (a < dmax) {
a = a + 1;
if (a * a + b * b - c == c * c) {
if (((a + b) > c) && ((b + c) > a) && ((c + a) > b)) {
printf("(%d, %d, %d)", a, b, c);
}
}
}
}
} while (c <= dmax);
}
move ++c; after the for loop instead of before.
This increments c to 2 before it even starts, but you want to include 1.
*Note, you may want to add conditions that prevent minimums of 0 or less.
If the value range for a, b and c is [dmin..dmax] (both inclusive), the sample looks like below:
for (c = dmin; c <= dmax; c++)
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; ++a)
{
if (a * a + b * b - c == c * c )
{
if (((a + b) > c) && ((b + c) > a) && ((c + a) > b))
{
printf("(%d, %d, %d)", a, b, c);
}
}
}
}
}
I'm doing this assignment for college in C, should be fairly simple, but a loop in it doesn't seem to terminate so the code won't work properly; even if I put in an i value to limit the amount of times it loops. Tried it with a for loop too, still gets stuck.
The code is supposed to take in values of coefficients and try to work out a root for a cubic equation by finding the midpoint between two large values and trying that out to see if it gets 0, if it doesn't, it should change one of the limits to the midpoint value. Here's the relevant code:
int main (void)
{
int i, u=1000, l=-1000;
float a, b, c, d, mid, y;
scanf(" %f %f %f %f", &a, &b, &c, &d);
while (abs(u - l) > 0.001 && i < 10)
{
mid= (u + l)/2;
y = a * pow(mid, 3) + b* pow(mid, 2) + c * mid + d;
if(y == 0) break;
else if(y < 0) l = mid;
else u = mid;
i++;
}
printf("\nThere is a root at: x = %.3f\n", mid);
}
Any help would be appreciated, thanks!
edit: Oh my god I'm an idiot. Always the small things. The code still isn't working but at least it's not stuck anymore, thanks guys!
You declared i, but did not initialize it, so it is set to whatever random value was left in memory.
For this example, lets say that value was -12,345.
Then i can be incremented over 12,000 times before it is greater than 10!
Your loop will run when i is incremented 12,355 times, and its value becomes 10, and the test i < 10 finally fails.
To fix this, initialize i = 0:
int i=0;
2 things. Initialize i to 0. this will ensure it terminates after 10 loops.
More important for your problem though, you have declared u and l as integers, I think you need to declare them as floats.
You need to initialize i: int i = 0;
This should work for you! You need to initialize i.
#include <stdio.h>
#include <math.h>
int main (void)
{
int i = 0, u = 1000, l =- 1000;
float a, b, c, d, mid, y;
scanf(" %f %f %f %f", &a, &b, &c, &d);
while (abs(u-l)>0.001 && i<10)
{
mid = (u + l)/2;
y = a*pow(mid,3) + b* pow(mid,2) + c*mid + d;
if(y == 0)
break;
else if(y<0)
l = mid;
else
u = mid;
i++;
}
printf("\nThere is a root at: x = %.3f\n", mid);
}
If you make u and l be floats then your while-loop terminates without i. Before that, abs(u-l) where u-l are ints will only terminate if a root is at zero. You also need to use fabs() instead of abs():
int main (void)
{
float u=1000.0, l=-1000.0;
float a, b, c, d, mid, y;
scanf(" %f %f %f %f", &a, &b, &c, &d);
while (fabs(u - l) > 0.001)
{
mid= (u + l)/2.0;
y = a * pow(mid, 3) + b* pow(mid, 2) + c * mid + d;
if(y == 0) break;
else if(y < 0) l = mid;
else u = mid;
}
printf("\nThere is a root at: x = %.3f\n", mid);
}
Seems like you still have something wrong in the bisection algorithm condition when you reset l and u to mid. I'm attaching a fixed version, and I used different variable names (sorry) to keep my head clear:
#define NMAX 1000
#define TOL 0.00001
int sign( float x ) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
int main (void)
{
int n=0;
float fa, fc, b=1000.0, a=-1000.0;
float p3,p2,p1,p0,c;
scanf(" %f %f %f %f", &p3, &p2, &p1, &p0);
while(n<NMAX)
{
c = (a + b)/2.0;
fc = p3*pow(c, 3) + p2*pow(c, 2) + p1*c + p0;
if(fc == 0.0 || (b-a)/2.0 < TOL ) break;
fa = p3*pow(a, 3) + p2*pow(a, 2) + p1*a + p0;
if( sign(fc) == sign(fa) )
a = c;
else
b = c;
n++;
}
if(n==NMAX) {
printf("Method failed.\n");
}
else {
printf("\nThere is a root at: x = %.3f\n", c);
}
}