Is condition evaluation optimized ? Is this code bad? - c++

1.Imagine condition if (obj.is_x() || obj.is_y() || obj.is_z())
Will obj.is_y() and obj.is_z() be called and evaluated if obj.is_x() returned true ?
2.Is this a bad idea(in general)? Does this code look bad ?
bool isbn13_prefix_valid (const string& prefix)
{
unsigned num = stoi(prefix);
if (num == 978 || num == 979) return 1; //super common ones
else if ( num >= 0 && num <= 5 || num == 7 || num >= 600 && num <= 649
|| num >= 80 && num <= 94 || num >= 950 && num <= 989
|| num >= 9900 && num <= 9989 || num >= 99900 && num <= 99999)
return 1;
return 0;
}

No, it will not, due to short-circuiting.
Yes, that code looks bad. Not because it's incorrect, but because you're stuffing an extremely long conditional into a single if statement. Try refactoring your code to make it cleaner.

Your code is absolutely fine. I'd like to see a comment where these strange numbers come from, that's all.
Turning it into a dozen trivial functions as has been suggested is in no way helpful. It actually makes it a lot harder to read the code, because it gets spread out over many many lines of code. Yes, it is complex. But that's due to the problem being complex, and trying to spread the complexity out doesn't help one bit.
Your actual question: In a || b, a is evaluated first. If it is true, then b is not evaluated and the result is true. If a is false, then b is also evaluated and the result is true or false, depending on the result of b.
An optimising compiler may start evaluating b before it has finished evaluating a, if it can prove that the evaluation of b has no side effects, and if it believes that (mostly due to parallelism in the hardware) it is on average faster to evaluate as much in parallel as possible, even if some things are evaluated when it wasn't necessary. But this is not noticable in the results of your code, and will only make the code faster.

Related

If else condition precedence in Verilog

I have noticed that there is a precedence of assignment while using if-else conditionals in Verilog. For example as in the code below:
if(counter < 6)
z <= 1;
else if(counter < 12)
z <= 2;
else
z <= 3;
I noticed that until the counter is less than 6, the value of z is assigned the value of 1 (z <= 1) and as soon as the value of the counter exceeds 6 and is less than 12, z is assigned the value 2 (z <= 2).
What if there are different variables used inside the conditionals as in the code below?
if(wire1_is_enabled)
z <= 1;
else if(wire2_is_enabled)
z <= 0;
What happens when both conditions are true? What is the behaviour of the assignment operator here?
I believe this is poor programming habit.
Yes, nested if-else branching statements naturally assume a priority in the order of execution. Think about using a case statement instead of deeply nesting if statements which are much more readable.
There is nothing wrong with this coding style unless you have code like:
if(counter < 6)
z <= 1;
else if(counter < 2)
z <= 2; // unreachable
else
z <= 3;
Then the statement z <= 2; becomes unreachable because when the first condition is false, the second condition can never be true. Fortunately there are a number of tools that can flag this problem for you.
Both if and case statements assume priority logic. However, you have an option to explicitly add a priority or unique keyword before the if or case keywords to declare and check your intent. See sections 12.4 and 12.5 in the IEEE 1800-2017 SystemVerilog LRM.
The 2 if/else statements behave the same way; the first condition to be true has the highest priority. Once a condition evaluates to true, all the following else clauses are ignored. Therefore, z <= 1 if both wire1_is_enabled and wire2_is_enabled are true. This is easy to prove to yourself with a simple simulation.
This is not a poor coding habit. This situation is common in Verilog. When you say programming, perhaps you are thinking of software languages. Keep in mind that these are hardware signals instead of software variables.

Why will my elseif statment never executed

Any idea why the else if statment will be never executed ? The value of difference is constantly changing when the program runs.
double difference = abs(reale_x[0] - reale_x[1]);
if (0 <= difference < 45) {
timer_counter += 1;
if (timer_counter == 30) {
cout << "CLICK" << '\n';
}
}
else if (difference > 50) {
timer_counter = 0;
}
That is not how comparation works in c++.
What this code
if (0 <= difference < 45) {
does is it first compares if 0 is smaller or equal to difference. It is then "replaced" by a bool value either true or false. And then a bool value (so either 1 or 0) is compared to 45. And it will always be smaller than 45. What you have there is an always true statement.
So the way you would write this if statement is
if (difference >= 0 && difference < 45){
Note that because of your else if statement it will not execute if the difference is >44 and <51
if (0 <= difference < 45) will be executed as if ((0 <= difference) < 45), which will be either 0<45 or 1<45 and will always be true. That's why the else part is not getting executed.
in mathematics, we see and write 0 <= x < 45 or something like that to define the range of the variable x. But in order to tell the computer the same thing, you have to tell more clearly. Saying, to have to tell the compiler, that the value of x is greater than or equal to zero and at the same time, that value will be less than 45, and you can tell the compiler by this statement: difference >= && difference < 45 . the && is an 'AND' operator in most of the languages.

Checking if a given group of integers contains a 0 value

Suppose I have a bunch of integers (10~20) and need to check if any of them equals 0. What's the most efficient way to do it? I don't want to evaluate a giant if(a=0 || b=0 || c=0 ||...) statement. I thought of if(abc... = 0) but if I remember correctly multiplication isn't a very quick process. Are there any other tricks, such as bit wise operations that would work? I'm trying to think as low level as possible to make this super efficient.
I'm pretty sure the fastest and clearest way to do this is with an explicit test:
int has_zero = !a || !b || !c || !d || !e ...;
Because the || and && are short-circuiting operators in C, evaluation stops as soon as the final result is known, so if (for instance) the b variable is zero, that satisfies the expression as true and stops evaluating the rest.
#AbhayAravinda suggested that !(a && b && c && d ...) might be more efficient, but I don't think so; because this is not so much doing an explicit not operation, but a low-level test-against-zero, this is a really easy test for pretty much any architecture to do reliably. I did a quick look at optimized assembler for both versions and there was no clear winner for performance, but I think the first version is clearer.
If every single cycle matters, then check both versions on your platform, but on my 64-bit Intel system, both gcc and clang do in fact generate the same assembly for both versions (with optimizations turned on).
Simple test code:
int a, b, c, d, e, f;
int test_or()
{
return !a || !b || !c || !d || !e || !f;
}
int test_and()
{
return ! (a && b && c && d && e && f);
}
int main()
{
return test_or() | test_and();
}
Compile this with gcc -S -O testfile.c and look at the resulting .s file.
Test each one in turn. Exploit the short-circuiting property of ||; place the variables in descending order of the probability of each being zero:
if (!a/*most likely to be zero*/ || !b || ...){
// one of them is zero
}
Most people give an answer like:
!a || !b || ...
(where a is the most probable one of being zero)
The idea is that, in case a is zero, then the rest of the sequence is not evaluated (because of not being necessary), which is a kind of optimisation, performed by the compiler.
This turns the question into: does your compiler perform this optimisation or not (and in case of "possibly yes", what are the parameters in order to enforce this)?
Can you tell us which compiler (version) you're working with? This might enable us verifying this.
You may look at the assembler output.
The !a || !b || !c || !d || !e || !f will give you a bunch of cmp and je statements. One pair for each variable. Because of boolean short cut evaluation, it may run very fast. Or not.
The maybe better and deterministic solution is using the bitwise AND operator. If one operand is 0, then the result will be 0. So someting like:
if (a & b & c & d & e & f & g & h & i & j & k)
will result in one mov and then and statements for each variable.
So, if the variable that is 0 is in the 2nd half of the if statement, then the bitweise AND will be faster.

Find a logical expression that is true if `n` is a multiple of `2019` and is not in the interval `(a, b)`

I had the task of finding a logical expression that would result in 1 if and only if a given number n is a multiple of 2019 and is NOT from the interval (a, b).
The textbook gave the following answer and I don't really understand it:
a>=n || b<=n && (n%3==0 && n%673==0)
The thing between those parantheses I understand to be equivalent to n%2019==0, so that's alright. But I don't understand why this works, I mean the && operator has higher priority that the || operator, so wouldn't we evaluate
b<=n && (n%3==0 && n%673==0)
first and only at the end if n<=a? I thought that if I were to do it, I would do it like this:
(a>=n || b<=n) && (n%3==0 && n%673==0)
So I just added that extra set of parantheses. Now we would check if the number is not in the interval (a, b), then we would check if it is a multiple of 2019 and then we would 'and' those to answers to get the final answer. This makes sense to me. But I don't understand why they omitted that set of parantheses, why would that still work? Shouldn't we consider that && has higher priority than ||, so we add an extra set of parantheses? Would it still work? Or is it me that is wrong?
Trying it out shows that the expression as written without the extra parentheses doesn't work:
bool expr(int n, int a, int b)
{
return a>=n || b<=n && (n%3==0 && n%673==0);
}
expr(1000, 2000, 2018) for example evaluates to true, even though it is not a multiple of 2019.
As you pointed out, the logical AND operator && has higher precedence than the logical OR operator || (reference), so the expression is equivalent to:
a>=n || (b<=n && (n%3==0 && n%673==0))
which is always true when n <= a, even if it's not a multiple of 2019.
A clearer expression would be:
(n % 2019 == 0) && (n <= a || n >= b)

C++ random numbers logical operator wierd outcome

I am trying to make a program generating random numbers until it finds a predefined set of numbers (eg. if I had a set of my 5 favourite numbers, how many times would I need to play for the computer to randomly find the same numbers). I have written a simple program but don't understand the outcome which seems to be slightly unrelated to what I expected, for example the outcome does not necessarily contain all of the predefined numbers sometimes it does (and even that doesn't stop the loop from running). I think that the problem lies in the logical operator '&&' but am not sure. Here is the code:
const int one = 1;
const int two = 2;
const int three = 3;
using namespace std;
int main()
{
int first, second, third;
int i = 0;
time_t seconds;
time(&seconds);
srand ((unsigned int) seconds);
do
{
first = rand() % 10 + 1;
second = rand() % 10 + 1;
third = rand() % 10 + 1;
i++;
cout << first<<","<<second<<","<<third<< endl;
cout <<i<<endl;
} while (first != one && second != two && third != three);
return 0;
}
and here is out of the possible outcomes:
3,10,4
1 // itineration variable
7,10,4
2
4,4,6
3
3,5,6
4
7,1,8
5
5,4,2
6
2,5,7
7
2,4,7
8
8,4,9
9
7,4,4
10
8,6,5
11
3,2,7
12
I have also noticed that If I use the || operator instead of && the loop will execute until it finds the exact numbers respecting the order in which the variables were set (here: 1,2,3). This is better however what shall I do make the loop stop even if the order is not the same, only the numbers? Thanks for your answers and help.
The issue is here in your condition:
} while (first != one && second != two && third != three);
You continue while none of them is equal. But once at least one of them is equal, you stop/leave the loop.
To fix this, use logical or (||) rather than a logical and (&&) to link the tests:
} while (first != one || second != two || third != three);
Now it will continue as long as any of them doesn't match.
Edit - for a more advanced comparison:
I'll be using a simple macro to make it easier to read:
#define isoneof(x,a,b,c) ((x) == (a) || (x) == (b) || (x) == (c))
Note that there are different approaches you could use.
} while(!isoneof(first, one, two, three) || !isoneof(second, one, two, three) || !isoneof(third, one, two, three))
You have a mistake in your logical condition: it means "while all numbers are not equal". To break this condition, it is enough for one pair to become equal.
You needed to construct a different condition - either put "not" in front of it
!(first==one && second==two && third==three)
or convert using De Morgan's law:
first!=one || second!=two || third!=three