C: Making an equation appears only once - c

I have following C code. The statement calculating simple_root appears twice. I am wondering if there is a better way to organise the code making the statement appear only once.
If putting the simple_root after the last else, there is a risk of error, e.g. the previous two conditions doesn't match. Please correct me if I am wrong.
if(fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_1)) < 1e-6)
{
triple_root = secDerivRoot_1;
simple_root = -b/a - 3*triple_root;
}
else if (fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_2)) < 1e-6)
{
triple_root = secDerivRoot_2;
simple_root = -b/a - 3*triple_root;
}
else
printf("Something is wrong. No common root with its 2nd derivative. \n");

You are missing something in the comment
If putting the simple_root after the last else, there is a risk of error, e.g. the previous two conditions doesn't match
This is already the case - if you don't match those two then triple_root and simple_root are already not set. I'm not sure how they are used after this piece of code or what your error handling is. You can either return immediately after the printf statement or set triple_root to be a NaN.
Then you can move the simple_root equation below the if statement. Alternatively you could put that in to a function. A one line function is fine and can make the code easier to understand.

I think the following should do it. I haven't compiled it or tested it so you may need to tweak something.
However your original formulation is much more readable and I really see no advantage to doing it this way.
And with this approach you are always doing both of the quartic_polynomial() calls rather than sometimes only doing one which may be much worse computationally speaking so far as CPU usage and time than duplicating a line of code.
I am curious if the two if statements could both be true. What are you to do in a case like that or can you just choose which ever you like?
{
int sec_1 = (fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_1) < 1e-6);
int sec_2 = (fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_2) < 1e-6);
if (! (sec_1 || sec_2)) {
printf("Something is wrong. No common root with its 2nd derivative. \n");
} else {
if (sec_1)
triple_root = secDerivRoot_1;
else
triple_root = secDerivRoot_2;
simple_root = -b/a - 3*triple_root;
}
}
Another approach, if a desire to prevent one statement from being updated and the other not would be something like the following:
#define SIMPLE_ROOT_CALC simple_root = -b/a - 3*triple_root
if(fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_1)) < 1e-6)
{
triple_root = secDerivRoot_1;
SIMPLE_ROOT_CALC;
}
else if (fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_2)) < 1e-6)
{
triple_root = secDerivRoot_2;
SIMPLE_ROOT_CALC;
}
else
printf("Something is wrong. No common root with its 2nd derivative. \n");
or even something like:
#define ROOT_CALC(x) triple_root = (x); simple_root = -b/a - 3*triple_root;
if(fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_1)) < 1e-6)
{
ROOT_CALC(secDerivRoot_1);
}
else if (fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_2)) < 1e-6)
{
ROOT_CALC(secDerivRoot_2);
}
else
printf("Something is wrong. No common root with its 2nd derivative. \n");
or perhaps depend on evaluation short circuit with the logical Or operator:
{
double x;
if (! (((x = secDerivRoot_1), fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_1) < 1e-6)) || ((x = secDerivRoot_2), fabs(quartic_polynomial(a, b, c, d, e, secDerivRoot_2) < 1e-6) )) ) {
printf("Something is wrong. No common root with its 2nd derivative. \n");
} else {
triple_root = x;
simple_root = -b / a - 3 * triple_root;
}
}

Related

Using 'continue' with boolean-based statements in C

For those of you who didn't understand - I KNOW this is NOT how a good code should look like... The purpose of this tricky question is to write a code without if-statements in order to practice boolean logic...
I'm trying to solve a question in C which restricts the programmer from using if/else/switch statements. cant use ternary operators either.
The idea is to use boolean based logical statements to get the "wanted path".
i.e - instead of:
if (1 > 0)
printf("TRUE")
else
printf("FALSE")
I would use:
bool res = true;
res = (1 > 0 && printf("TRUE")) || printf("FALSE")
(this is the general idea, using the boolean statement processing logic to manipulate different actions.
The only problem I ran into was to replace a part that looks somewhat like this (where i want the program to skip a certain part of the loop if A is equal to B):
while (...)
{
if (A == B)
continue;
//code
}
Do you know if this is possible to execute without using if/else/switch statements?
Thanks!!
The equivalent of your
while (condition)
{
foo();
if (A == B)
continue;
bar();
baz();
}
is
while (condition)
{
foo();
(A != B) && bar();
(A != B) && baz();
}
This assumes bar() doesn't change A or B. If it does, use a temporary variable:
while (condition)
{
foo();
bool cond = A != B;
cond && bar();
cond && baz();
}
Do you know if this is possible to execute without using if/else/switch statements?
With gcc extension statement expressions you can do this:
int main() {
int A, B;
while (1) {
A == B && ({continue;0;});
}
}
Please don't do this and please don't do res = (1 > 0 && printf("TRUE")) || printf("FALSE"). Just write ifs.
Assuming OK to use state variable then
while (...)
{
if (A == B)
continue;
//code
}
Can be implemented as
state = true ;
while ( ... ) {
...
while ( a == b ) {
state = false ;
break ;
} ;
while ( !state ) {
// code here
break ;
} ;
}
Or with fewer clutter, if allowed:
while (...)
{
state = A == B ;
while ( state ) {
//code here
break ;
} ;
}
With relatively minor performance penalty from having to double-test.
Side note: In my undergrad studies (many years ago), I recall hearing a lecture that explain that ALL control flow commands (if, while, do {} while, switch, with the exception of goto), can be implemented using the while. I wish I can find the reference/proof for that. This was part of a lecture about code verification.
if (1 > 0)
printf("TRUE")
else
printf("FALSE")
I would use:
bool res = true;
res = (1 > 0 && printf("TRUE")) || printf("FALSE")
If I see such a code written by any programmer in my team I would fire him/her.
Why? Your version is not human readable, it is error prone and almost not debugable.

Alternative syntax of combining multiple condition check

I am implementing a simple if statement in c, where I am comparing the value of integer 'tile' to four other integers: w, a, s and d.
Here is my code:
if(tile == w || tile == a || tile == s || tile == d )
{
printf("legal\n");
return true;
}
While the above is correct, the syntax is tiresome. Is there a more elegant way of writing the condition "'tile' is one of the following integers..."
I'm a novice in programming so I apologise as I suspect the answer is very obvious. I've failed to find it addressed elsewhere though.
While eyalm's answer is maybe the one you're looking for, just wanted to chime in to point you to a more important factor here (as you mentioned, "I'm a novice in programming"), which is "Write code which is easier for humans to understand".
While the bitwise approach is shorter, it generally appears to be more difficult to understand a maintain, as it grows.
A cleaner approach will be (while it takes more effort to write the code), stick to the if ( a || b || c) syntax, or a fall-though switch case. It gives better readability.
In case your options grows longer (that you may need a horizontal scroll bar), you can consider adding a function to get the required value checked and use the return value in the condition in the if statement.
The bottom line is, there is no right or wrong way, only choose the way which make the code more readable and maintainable.
Two options i can think of...
bitwise
#define TILE_W 0x0001
#define TILE_A 0x0002
#define TILE_S 0x0004
#define TILE_D 0x0008
if (tile&(TILE_w|TILE_A|TILE_S|TILE_D))
{
printf("legal\n");
return true;
}
switch-case
switch (tile)
{
case w:
case a:
case s:
case d:
printf("legal\n");
return true;
default:
return false;
}
Solution for improvement can depend on values which you compare with.
If w, a, s and d are integer numbers that have consecutive values (e.g. 10, 11, 12 and 13), if-statement can use condition for boundaries:
if( tile >= w && tile <= d) { printf("legal\n"); }
If values are disparate (e.g. 6, 32, 142, 55), you can use switch..case construction, like
switch (tile)
{
case w:
case a:
case s:
case d:
printf("legal\n");
break;
default:
printf("ILLEGAL\n");
break;
}
Also you can use setting flag in one or multiple if as
int legal = 0;
// checking can be in different places of code
if (tile == w)
legal = 1;
if (tile == a || tile == s)
legal = 1;
if (tile == d)
legal = 1;
if( legal )
{
printf("legal\n");
}
And consider storing w, a, s and d values as array of valid values, so loop can be used for checking:
int valArr[] = {101, 151, 333, 7}; // you can add any number of values here
int i;
int legal = 0;
for(i = 0; i < ( sizeof(valArr)/sizeof(valArr[0]) ); i++)
{
if(valArr[i] == tile)
{
legal = 1;
break;
}
}
if( legal )
{
printf("legal\n");
}
else
{
printf("ILLEGAL\n");
}

Function definition not allowed / [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
My professor gave us this code in class to show how a program works and said "go home and try it and you'll see it works".... well after 30 minutes I cannot get it to run. can someone please help me and point me in the right direction. Thank you!
-I get function definition on the end "double g(double x)"
-On the first else where x_left = x_mid control reaches end of non-void function
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define FALSE 0
#define TRUE 1
#define NO_ROOT -99999.0
//function prototypes
double bisect(double, double, double, double f(double farg));
// evaluation of function
double g(double);
double h(double);
int main(void) {
double x_left, x_right, epsilon, root; //declare variables
// get endpoint and error tolerance
printf("\nEnter interval endpoints > ");
scanf("%lf%lf", &x_left, &x_right);
printf("\nEnter tolerance > ");
scanf("%lf", &epsilon);
//use bisect function to look for roots of functions
printf("\n\n For function g(x)");
root = bisect(x_left, x_right, epsilon, g);
if (root != NO_ROOT)
printf("\n g(%.7f) = %e\n", root, g(root));
printf("\n\n For function h(x)");
root = bisect(x_left, x_right, epsilon, h);
if (root != NO_ROOT)
printf("\n h(%.7f) = %e\n", root, h(root));
system("pause");
return (0);
}
// bisection method program coding
double bisect(double x_left, double x_right, double epsilon, double f(double farg)){
double x_mid, f_left, f_right, f_mid;
int root_found;
// computes function at initial end points
f_left = f(x_left);
f_right = f(x_right);
// if no change in sign
if (f_left * f_right > 0) {
printf("\nmay not be no root in [%.7f, %.7f]\n\n", x_left, x_right);
return NO_ROOT;
}
// searches as long as interval size is large enough
root_found = FALSE;
while (fabs(x_right - x_left) > epsilon && !root_found) {
// compute the mid point
x_mid = (x_left + x_right) / 2.0;
f_mid = f(x_mid);
if (f_mid == 0.0) {
root_found = TRUE;}
else if (f_left * f_mid < 0.0) {
x_right = x_mid;
} else {
x_left = x_mid;
}
// trace loop execution
if (root_found)
printf("\nRoot found at x = %.7f , midpoint of [%.7f, %.7f] ", x_mid, x_leftx_right);
else
printf("\nNew interval is [%.7f, %.7f] \n\n", x_left, x_right);
//if there is a root
return ((x_left + x_right)/2.0);
}
// functions for which roots are sought
double g(double x){
return (5 * pow(x, 3.0) - 2 * pow(x, 2.0) +3);
}
double h(double x){
return (pow(x, 4.0) - 3 * pow(x,2.0) - 8);
};
}
I get an error on this line:
printf("\nRoot found at x = %.7f , midpoint of [%.7f, %.7f] ", x_mid, x_leftx_right
saying that x_leftx_right is undeclared.
If I change this to x_left, x_right then it compiles OK except for "undefined reference to g" and "undefined reference to h".
The reason for the undefined reference to g is that you never provided a function definition for the function g that was prototyped by double g(double);. You did provide a nested function g within bisect. Nested functions are a non-standard extension, and bisect::g is a different function to g. Similarly for h.
To fix this, move the definitions of g and h to be after the end of the bisect function; instead of inside that function.
The reason for your "control reaches end of non-void function" warning is probably because there is no return statement after the while loop.
Your line return ((x_left + x_right)/2.0); line is within the loop begun by while (fabs(x_right - x_left) > epsilon && !root_found) {. If this loop finishes by the loop condition no longer being true, then the execution hits the end of the function without returning anything.
NB. If you indent your code properly so that you line up { then you are less likely to have this sort of problem. Your editor should have a key that you can use to find matching curly-braces. Also, operating your compiler in strict standard mode would have given an error about the use of nested function.
`

Working out if an array of line segments intersect

I have been asked to store and draw an array of linesegments.
The program should print the message "No intersection" or "Found an intersection" (depending) before terminting if negative coordinates are entered or 2x MAXSEGMENTS segments have been entered.
int main(void) {
lineSeg_t line, allsegments[MAXSEGMENTS];
point_t a, b;
int pointssofar=0, i, v, w, x, y;
OpenGraphics();
while (pointssofar<=(2*MAXSEGMENTS)){
a=GetPoint();
x=XCoord(a);
y=YCoord(a);
if ((x<0)||(y<0))
break;
b=GetPoint();
v=XCoord(b);
w=YCoord(b);
if ((v<0)||(w<0))
break;
line=LineSeg(a, b);
DrawLineSeg(line);
allsegments[((pointssofar+2)/2)]=line;
for (i=0;i<(pointssofar/2);i++){
if (intersect(line, allsegments[i])==TRUE){
printf ("Found an intersection");
pointssofar=2*MAXSEGMENTS;
} else if (pointssofar==(2*MAXSEGMENTS)){
printf("No intersection");
}
}
}
for(i=0;i<(pointssofar/2);i++){
if (intersect(allsegments[pointssofar/2], allsegments[i])==FALSE){
printf("No intersection");
}
}
}
I'm having trouble outputting the messages. Think I'm stuck in the while loop and I'm really not sure how to get out!
Thank you in advance.
your while loop will never terminate, because there is no line in it that will ever make it's condition not true.
while (pointssofar<=(2*MAXSEGMENTS)){
the only time you change any of those values is that you get is
pointssofar=2*MAXSEGMENTS;
which satisfy the while loop condition.
you also have 2 break statements, but those are entirely dependant on the XCoord and YCoord functions. They might not ever actually be returning negative numbers.
You don't seem to increment pointssofar unless you find an intersection.

Variable value changes for no apparent reason

In my code I define a step size "h" before a while loop. Somehow it seems to change by itself when I try to use it in the loop. If I define it inside the loop it seems to be ok, but the data I get doesn't seem to be right so I'm guessing the problem might be related.
Even when I print it at this location (see the printf in the code) the output is 3 values and I have no idea why. If you see anything else that's not related but seems wrong please tell me, as I said I'm getting unexpected values (it may just be my formulas).
int main()
{
FILE *f1;
f1 = fopen("Question2 part 3 solution.txt", "w");
double r0=0.05;
double dr0=-a*a*r0/sqrt(1+pow(a*a*r0,2)),h=0.01;
double k[4][3],x[]={dr0,z0,T0,r0},x1[]={0,0,0,0}, s=0;
int i,j;
while(s<=1)
{
//Runge-Kutta
for (j=0;j<4;j++)
{
for (i=0;i<4;i++)
{
if (j==0){k[i][0]=h*System(i,x[0],x[1],x[2],x[3]);}
if (j==1){k[i][1]=h*System(i,x[0]+k[0][0]/2.0,x[1]+k[1][0]/2.0,x[2]+k[2][0]/2.0,x[3]+k[3][0]/2.0);}
if (j==2){k[i][2]=h*System(i,x[0]+k[0][1]/2.0,x[1]+k[1][1]/2.0,x[2]+k[2][1]/2.0,x[3]+k[3][1]/2.0);}
if (j==3){k[i][3]=h*System(i,x[0]+k[0][2],x[1]+k[1][2],x[2]+k[2][2],x[3]+k[3][2]);}
}
}
for (i=0;i<4;i++)
{
x[i]=x[i]+(k[i][0]+2.0*k[i][1]+2.0*k[i][2]+k[i][3])/6.0;
}
printf("%8.3lf",h);
s+=h;
}
fclose(f1);
return(0);
}
double System(int i,double dr, double z, double T, double r)
{
//printf("%e\t%e\t%e\t%e\n",dr,z,T,r);
if (T==T0 && z==z0 && i==0) {return (-a*a*dr)*pow(1-dr*dr,3/2)/2.0;}
if (i==0 && T!=0){return (-a*a*r*(1-dr*dr)-dr*sqrt(1-dr*dr))/T;}
if (i==1){return (-sqrt(1-dr*dr));}
if (i==2){return (-a*a*r*dr+sqrt(1-dr*dr));}
if (i==3){return (dr);}
//if (i==3){return (-m2*l1*l2*B*theta1dt*theta2dt*sin(theta2-theta1)-l2*m2*g*B*sin(theta2));}
}
Thanks in advance!
See the declaration of k:
double k[4][3]
And then see this statement
k[i][3]=...
Here you write beyond the boundaries of the array, leading to undefined behavior.
You are overrunning the memory, variable k is defined as double k[4][3], but you are updating k[i][3]when j==3

Resources