How to simplify if statements - c

How can I simplify below if statements?, I'm trying to achieve the possibly most efficient code.
// doSomething based on x value and y value
void doSomething(x int, y int) {
//x not zero and y not zero
if (x != 0 && y != 0) {
//do a
//do b if x greater or equal y
//else do c
if (x >= y) {
//do b
} else (x < y) {
//do c
}
return;
}
//do b if x not zero and y zero
if (x != 0 && y == 0) {
//do b
return;
}
//do e if both x and y zero
if (x == 0 && y == 0) {
//do e
return;
}
}
What is the most concise and efficient way to simplify?

As it stands, your code is equivalent to:
if (x == 0)
{
if (y == 0)
do e
}
else if (y != 0)
{
if (x < y)
do a,c
else
do a,b
}
In particular:
if x=0 && y!=0 or y=0 && x!=0, then do nothing;
the two branches //do b if x not zero and y zero and //do d if x zero and y not zero are unreachable in your code.

History:
The code in the question was changed several times. This answer is based on the original version of the code. That code is shown below, minimally modified so that it's compilable C code:
void original(int x, int y)
{
if (x == y && x != 0 && y != 0) {
// do a
// do b
return;
}
if (x < y && x != 0 && y != 0) {
// do a
// do c
return;
}
if (x > y && x != 0 && y != 0) {
// do a
// do b
return;
}
if (x != 0 && y == 0) {
// do a
// do b
return;
}
if (x == 0 && y != 0) {
// do a
// do d
return;
}
if (x == 0 && y == 0) {
// do e
return;
}
}
Motivation:
The advantage of the original code is that it clearly covers all possible input combinations.
The first three if statements handle the cases where x and y are non-zero (with x==y, x<y, and x>y handled separately). Then the remaining three if statements handle the cases where one or both are zero. That covers everything.
The disadvantages of the original code are:
Many of the comparisons are repeated several times, e.g. y != 0 is checked four times. Given that branching statements tend to be time consuming in contemporary (year 2021) processors, redundant comparisons are something to be avoided 1.
The code violates the DRY principle. Specifically, do a appears in five locations, and do b appears in three locations. So any refactoring of the code should attempt to eliminate the repetition.
1) The optimizer may be able reduce the number of comparisons. However, that's hard to test without real code.
Refactoring with nested if statements:
If we focus on the DRY principle first, we notice that a appears in 5 of 6 code blocks. Only the case for e doesn't invoke a. So the logical choice is to handle e first. This results in the following code structure:
if (x == 0 && y == 0) {
// do e
} else {
// do a
// everything else (note that either x is not zero, or y is not zero)
}
Within the "everything else", we have do b three times, do c once, and do d once. So the next step is to handle c and d, leaving only b. The refactored code looks like this:
void nestedIf(int x, int y)
{
if (x == 0 && y == 0) {
// do e
} else {
// do a
if (x == 0) {
// do d
} else {
if (y != 0 && x < y) {
// do c
} else {
// do b
}
}
}
}
Refactoring with early return statements:
Some coding standards insist that a function shall only return from one location. The nested if code meets that requirement, but at the cost of being a little messy due to nesting. Using early returns eliminates the nesting, and may allow the code for a thru e to be implemented inline without additional functions (assuming they're only a few lines each). The refactored code looks like this:
void earlyReturn(int x, int y)
{
if (x == 0 && y == 0) {
// do e
return;
}
// do a
if (x == 0) { // x is zero and y is not zero
// do d
return;
}
if (y != 0 && x < y) { // x and y are both not zero, and x < y
// do c
return;
}
// do b
}

assuming a(), b(), and e() have the same type (fxtype)
fxtype *fx[4] = { e, NULL, b, a }; // NULL when x==0, y!=0
fx[2*!!x + !!y](x, y);
Change a to include c() and b()
int a(int x, int y) {
// do previous a()
if (x < y) c(x, y); else b(x, y);
return 0;
}

Related

Short circuiting if statement

Say you have this nested if-statement:
int *x;
int y;
if (x == NULL || y > 5)
{
if (x != NULL)
// this should print if x != NULL and y > 5
printf("Hello!\n");
// this should only print if x == NULL.
printf("Goodbye!\n");
}
return 0;
Here, if either statement is true, it will return the same value (0). We should only print "Goodbye" if the left side of the outside if statement is true, regardless of whether the right hand side is true or false. Is it possible to eliminate the inside if-statement by short-circuiting, turning this into a single if-statement?
If I have understood correctly what you need is the following
if ( x == NULL )
{
printf("Goodbye!\n");
}
else if ( y > 5 )
{
printf("Hello!\n");
}
Otherwise if the first compound statement includes other statements that have to be executed in case when x == NULL or y > 5 then the if statements can look like
if ( x == NULL || y > 5)
{
// common statements that have to be executed when x == NULL or y > 5
//...
if ( !x )
{
printf("Goodbye!\n");
}
else
{
printf("Hello!\n");
}
}
This will only print Goodbye if x is NULL and y > 5
if (x == NULL || y > 5)
{
if (x != NULL)
// this should print if x != NULL and y > 5
printf("Hello!\n");
else
// this should only print if x == NULL.
printf("Goodbye!\n");
}

Understanding calling one function inside another C

I'd like to ask the following misunderstandings of C language, which I see I'm having.
I'm sorry if the code is not properly indented, I tried as much as I could but there are not so many guides on the internet.
The program asked given a starting number 'val' and a Even-Odd or Odd-Even alternating sequence (which stops whenever this rules is violated) to print the greater prime number with 'val'.
I tried with two functions and the main: one to control the GCD between two given numbers and the other to keep tracks of the greatest one, but I think I miss something in the code or in the conception of C function,
Because when compiled it returns me 0 or great number which I'm not entering.
One example to understand what I should do:
If my sequence was 10, 7, 8, 23 and my val was 3, I had to print 23, because it is the greatest integer prime with 3.
Here's the code :
#include <stdio.h>
int mcd(int a, int b)
{ // Gcd function
if (a == 0)
return b;
else
return mcd(b % a, b);
}
int valuta(int val, int h) // Valuing Max function
{
int temp = 0;
if (mcd(val, h) == 1 && h > temp)
temp = h;
return temp;
}
int main()
{
int val, d, x, y, z, t, contatore = 1;
scanf("%d", &val);
scanf("%d%d", &x, &y);
if (x > y && mcd(val, x) == 1)
{ // Two options
t = x;
}
else if (y > x && mcd(val, y) == 1)
{
t = y;
}
if ((x % 2 == 0 && y % 2 == 0) || (x % 2 == 1 && y % 2 == 1))
{ // Bad case
if (x > y && mcd(val, x) == 1)
{
t = x;
contatore = 0;
}
else if (y > x && mcd(val, y) == 1)
{
t = y;
contatore = 0;
}
}
else
{
while (contatore == 1)
{
scanf("%d", &z);
t = valuta(val, z);
if (x % 2 == 0 && z % 2 == 0)
{ // Even- Odd - Even
scanf("%d", &d);
t = valuta(val, d);
if (d % 2 == 0)
{
contatore = 0;
}
else
{
contatore = 0;
}
}
if (x % 2 == 1 && z % 2 == 1)
{ //Odd- Even- Odd
scanf("%d", &d);
t = valuta(val, d);
if (d % 2 == 1)
{
contatore = 0;
}
else
{
contatore = 0;
}
}
}
}
printf("%d\n", t);
return 0;
}
PS. Is there any way to reduce the number of lines of code or to reduce the effort in coding? I mean, a straightforward solution will be helpful.
Your valuta() function is flawed in that it needs to return the maximum qualifying value so far but has no knowledge of the previous maximum - temp is always zero. The following takes the previous maximum as an argument:
int valuta(int val, int h, int previous )
{
return ( mcd(val, h) == 1 && h > previous ) ? h : previous ;
}
And is called from main() thus:
t = valuta( val, x, t ) ;
The test mcd(val, h) == 1 is flawed, because mcd() only ever returns the value of parameter b which is not modified in the recursion, so will never return 1, unless the argument b is 1. Since I have no real idea what mcd() is intended to do, I cannot tell you how to fix it. It appear to be a broken implementation of Euclid's greatest common divisor algorithm, which correctly implemented would be:
int mcd(int a, int b)
{
if(b == 0)
return a;
else
return mcd(b, a % b);
}
But I cannot see how that relates to:
"[...] he greatest integer prime with 3 [...]
The odd/even even/odd sequence handling can be drastically simplified to the extent that it is shorter and simpler than your method (as requested) - and so that it works!
The following is a clearer starting point, but may not be a solution since it is unclear what it is it is supposed to do.
#include <stdio.h>
#include <stdbool.h>
int mcd(int a, int b)
{
if(b == 0)
return a;
else
return mcd(b, a % b);
}
int valuta(int val, int h, int previous )
{
return ( mcd(val, h) && h > previous ) ? h : previous ;
}
int main()
{
int val, x, t ;
printf( "Enter value:") ;
scanf("%d", &val);
typedef enum
{
EVEN = 0,
ODD = 1,
UNDEFINED
} eOddEven ;
eOddEven expect = UNDEFINED ;
bool sequence_valid = true ;
printf( "Enter sequence in odd/even or even/odd order (break sequence to exit):\n") ;
while( sequence_valid )
{
scanf("%d", &x);
if( expect == UNDEFINED )
{
// Sequence order determined by first value
expect = (x & 1) == 0 ? EVEN : ODD ;
}
else
{
// Switch expected odd/even
expect = (expect == ODD) ? EVEN : ODD ;
// Is new value in the expected sequence?
sequence_valid = (expect == ((x & 1) == 0 ? EVEN : ODD)) ;
}
// If the sequence is valid...
if( sequence_valid )
{
// Test if input is largest qualifying value
t = valuta( val, x, t ) ;
}
}
// Result
printf("Result: %d\n", t);
return 0;
}

How does 'if((x) || (y=z))' work?

I don't quite understand how the if statement in this case works. It evaluates the x != 0 statement and when that is not true anymore, it assigns z to y and then breaks the if statement?
int main()
{
int x, y, z, i;
x = 3;
y = 2;
z = 3;
for (i = 0; i < 10; i++) {
if ((x) || (y = z)) {
x--;
z--;
} else {
break;
}
}
printf("%d %d %d", x, y, z);
}
Let's decompose that into smaller bits.
if (x) is the same as if (x != 0). If x != 0, then you know the condition is true, so you don't do the other portion of the if.
If part 1. was false, then y = z assigns z into y and returns the final value of y.
From point 2., we can understand that if (y = z) is equivalent to y = z; if (y != 0)
Thus, from points 1. and 3., we can understand that :
if ((x) || (y = z)) {
doSomething();
}
else {
doSomethingElse();
}
Is the same as :
if (x != 0) {
doSomething();
}
else {
y = z;
if (y != 0) {
doSomething();
}
else {
doSomethingElse();
}
}
It's true it's not particularly readable code though.
No. if ((x) || (y = z)) {
in C-English is basically:
if x is nonzero, evaluate the following code.
if x is zero, set y to z.
if y is nonzero, evaluate the following code.
otherwise, break out of the loop.
If x is zero or y is zero, it breaks out of the loop.
int main()
{
int x = 3;
int y = 2;
int z = 3;
unsigned int i;
for (i = 0; i < 10; i++)
if (x != 0) {
x = x-1;
z = z-1;
}
else {
y = z;
if (y != 0) {
x = x-1;
z = z-1;
}
else {
break;
}
}
}
printf("%d %d %d", x, y, z);
}
In C, there is short-circuiting, so the statement y=z will not be evaluated until x becomes zero.
When x == 0, since z also decrements the same way, z == 0. Hence y will also be zero at that time due to the assignment. The statement y=z also returns y at this point which will be evaluated as a condition, and since that is also 0, the else break will be hit.
Hence I believe the answer should be 0 0 0.
When you use assignment in an if statement, the result of the assignment is returned. so when you write :
if (x = y)
It will be always true unless the value of y is 0, so 0 is returned as the result of assigning and the if statement is not executed.(anything except 0 is considered as true.)
So when you write :
if ( x || (x = y))
The if statement doesn't execute only if x is 0 & y is 0.
Here
if ((x) || (y = z))
there are two condition
one condition is
if ((x)) and another condition is if ((y = z))
if one of them is true then if portion is execute otherwise else condition work
only and only when both condition are false then else execute.

What's the difference between R's R_pow() and libc's pow()?

The Writing R Extensions manual, Sec. 6.7.3., states that the R API function declared as double R_pow (double x, double y) computes x^y:
[...] using R_FINITE checks and returning the proper result (the same as R) for the cases where x, y or i are 0 or missing or infinite or NaN.
However, I cannot find such x and y for which the pow() function from the C library gives improper results. I tried various cases, like x, y beingInf,NA/NaN, integers, and so on, but I found no input data that generated the results different than those returned by ordinarypow()`.
Rcpp::evalCpp("::pow(1.124e-15, 2)", includes = "#include <cmath>") == Rcpp::evalCpp("R_pow(1.124e-15, 2)")
## [1] TRUE
Maybe you guys will provide me with some improper example.
BTW, I'm using gcc 4.8.2 with glibc 2.18 (Fedora 20, x86_64).
For R_pow()'s source code search for R_pow here.
It may just be easiest to look at the source code from which I copied the actual function:
double R_pow(double x, double y) /* = x ^ y */
{
/* squaring is the most common of the specially handled cases so
check for it first. */
if(y == 2.0)
return x * x;
if(x == 1. || y == 0.)
return(1.);
if(x == 0.) {
if(y > 0.) return(0.);
else if(y < 0) return(R_PosInf);
else return(y); /* NA or NaN, we assert */
}
if (R_FINITE(x) && R_FINITE(y)) {
/* There was a special case for y == 0.5 here, but
gcc 4.3.0 -g -O2 mis-compiled it. Showed up with
100^0.5 as 3.162278, example(pbirthday) failed. */
return pow(x, y);
}
if (ISNAN(x) || ISNAN(y))
return(x + y);
if(!R_FINITE(x)) {
if(x > 0) /* Inf ^ y */
return (y < 0.)? 0. : R_PosInf;
else { /* (-Inf) ^ y */
if(R_FINITE(y) && y == floor(y)) /* (-Inf) ^ n */
return (y < 0.) ? 0. : (myfmod(y, 2.) ? x : -x);
}
}
if(!R_FINITE(y)) {
if(x >= 0) {
if(y > 0) /* y == +Inf */
return (x >= 1) ? R_PosInf : 0.;
else /* y == -Inf */
return (x < 1) ? R_PosInf : 0.;
}
}
return R_NaN; // all other cases: (-Inf)^{+-Inf, non-int}; (neg)^{+-Inf}
}
which shows in which cases this collapses to pow(x, y).

How do I skip checking for my position

for (int x = 0; x <= battleField.getCols(); x++){
for (int y = 0; y <= battleField.getRows(); y++){
if ((battleField.get(x,y) == team) && ((x + y)
!= battleField.get(row, col)))
{
.
.
.
}
}
}
battleField.get(row, col) will return my position on a grid now my question is that how do I skip my self from checking where my position is ? because when the for loop checks for x and y it goes through the whole grid. What do I have to do?
Assuming the variables for your current position are named current_x and current_y, then you could do something like this inside your loop...
bool isMyPosition = (x == current_x) && (y == current_y);
if ( !isMyPosition
&& (battleField.get(x,y) == team)
&& ((x + y) != battleField.get(row, col)))
{
...
}
Instead of
((x + y) != battleField.get(row, col))
I think you want
(x != row && y != col)
If you did want that first part you could just add this to the beginning of your inner for loop:
for (int x = 0; x <= battleField.getCols(); x++){
for (int y = 0; y <= battleField.getRows(); y++){
if(x == row && y == col) // This will check if the loop is looking at your position
continue; // This will go to the next step in the "y" for loop, essentially skipping the rest of the code in this block
if ((battleField.get(x,y) == team) && ((x + y)
!= battleField.get(row, col)))
{
.
.
.
}
}
}
if(Question.IsAbout(EscapingOnCheck))
Most languages have some kind of continue that can be used to escape a loop when a condition is met.
else
Save your current position in some variables, and add another nested loop (for debugging's sake) or add an && clause (for less code's sake)

Resources