C++ comparison of integers with float [duplicate] - c++

This question already has answers here:
Checking if a value is within a range in if statment [duplicate]
(2 answers)
Closed 6 years ago.
I have the following code.that demonstrates the problem I am having. How come the comparison is not evaluating to true? Is this a limitation of integer and floating point comparisons?
#include <iostream>
int main(){
double m = -0.625;
if((-1)<=m<=0){
std::cout << "Enter here" <<std::endl;
}
return 0;
}

You can't do three way comparison like that in C. Change it to the following and it'll work:
if((-1) <= m && m <= 0){
std::cout << "Enter here" <<std::endl;
}

The condition in this if statement
if( ( -1 ) <= m <= 0 ){
is equivalent to
if( ( -1 <= m ) < = 0 ){
as -1 is less than m then the subexpression ( -1 <= m ) yields 1 in C and true in C++ that then is converted to 1 and the subexpression 1 <= 0 yields 0 in C and false in C++..
To get the expected result you should write instead
if( -1 <= m && m <= 0 ){

In C++ -1 <= m <= 0 is equivalent to (-1 <= m) <= 0.
In this example, -1 is implicitly converted to a float in order to use the <= operator with m. The result of this expression is a bool. This result is then implicitly converted to an int in order to use the <= operator with 0. Since a bool is converted to either 0 or 1 (false or true), this conditional statement will only be true when m is less than -1.
It makes sense from a math standpoint to structure the if statement like that, however you must break it up explicitly so the compiler knows what you want.
Try this
-1 <= m && m <= 0

Related

if statements and relational and comparison operators: "Exceptions" When comparing three values/variables [duplicate]

This question already has answers here:
Is (4 > y > 1) a valid statement in C++? How do you evaluate it if so?
(5 answers)
Closed 1 year ago.
Context
Taking a c++ course and if statements and relational and comparison operators came up. I don't know enough c++ vocabulary so I apologize if this question has been asked before. I tried searching around, but I didn't find anything.
Problem
Below illustrates an example of what I am confused about.
int n = 1;
if(2 < n <1){
cout << n << endl;
}
When the program is ran, the cout statement gets printed to the console (which is surprising to me).
Question
How is C++ interpreting the values and relational and comparison operators within the if statement?
If there are any other interesting "exceptions" like this documented somewhere could you please reference it for me, thank you.
Ans Attempt
I'm not totally sure what is going on. To me it seems like the middle number is getting skipped?
After playing with the numbers a few times I've now been able to confirm that the middle number is getting skipped, but I have no idea why.
If I add arguments by scaling the problem up:
if(2 < n < 0 <1){
cout << n << endl;
}
and also:
if(2 < n < 1 < 1 < 1){
cout << n << endl;
}
Now I get really confused. It seems like whatever "thing" is in the middle gets ignored. But I found an exception to my pattern when n = 3 causes the if statement to be "false":
int n = 3
if(2 < n < 1 < 1 <1){
cout << n << endl;
}
But then if I change n to what seems like "any" (not exhaustive) other number the if statement will yield true again.
The 2 < n < 1 ain't does what you think it should:
Because these operators group left-to-right, the expression a<b<c is
parsed (a<b)<c, and not a<(b<c) or (a<b)&&(b<c) - cppreference.com
The 2 < n part will return a Boolean value which in turn will be compared in the < 1.
2 < n < 1;
// equal to
(2 < n) < 1;
So, in total, the 2 < n < 1 flows like so:
(2 < n) < 1. Is n greater than 2? No, return false.
false < 1. The false is promoted to an integer, to 0. Is 0 less than 1? Yes, the if condition is true.
That's why when n == 3 in the 2 < n < 1 < 1 < 1, the overall you get false:
(2 < 3) < 1 < 1 < 1. Is 3 greater than 2? Yes! Returns 1 (true)
(1 < 1) < 1 < 1. Is 1 less than 1? No! Return 0 (false)
(0 < 1) < 1. Is 0 less than 1? Yes! Return 1 (true)
1 < 1. Is 1 less than 1? No! Return 0 (false)
It is nonsensical as you can see. In order to make it work, you will have to make explicit checks:
(n < 2) && (n > 1)
// is n less than 2 AND is n greater than 1

Issues with commutative property of && operator

The code below that I have been having strange issues with is meant to trim off the unused portion of an integer array, and then convert it into a string.
Ex:
_ABC__DE______ would become _ABC__DE.
The problems show up when the input is filled with the default character. ("_" in the example).
sLength is the length of the integer array chars
The problematic code:
int inputLength = sLength - 1;
while (chars[inputLength] == defaultChar && inputLength >= 0) {
inputLength--;
}
inputLength++;
Serial.println("input length: " + String(inputLength));
// (in)sanity check
Serial.println(inputLength);
Serial.println(String(inputLength));
Serial.println(inputLength <= 0);
Serial.println(0 <= 0);
Serial.println(inputLength == 0);
Serial.println(0 == 0);
if (inputLength <= 0) {
//reset cursor position
Serial.println("index set to 0");
index = 0;
} else {
output = "";
for (int i = 0; i < inputLength; i++) {
char c = charSet[chars[i]];
if (c == '_') {
c = ' ';
}
output += c;
}
done = true;
}
The output when given an array filled with defaultChar:
input length: 0
0
0
0
1
0
1
If I'm interpreting correctly, the output means that 0 > 0 and 0 =/= 0 on even lines, but 0 <= 0 and 0 = 0 on odd lines.
The workaround I've come up with is replacing
while (chars[inputLength] == defaultChar && inputLength >= 0) {
inputLength--;
}
with one of the following
while (inputLength >= 0 && chars[inputLength] == defaultChar) {
inputLength--;
}
.
while (chars[inputLength] == defaultChar) {
inputLength--;
if (inputLength < 0) {
break;
}
}
which both result in an output of:
input length: 0
0
0
1
1
1
1
index set to 0
Why does this change the result?
As far as I knew until now, the && operator was commutative.
Is there something that I am missing that makes
chars[inputLength] == defaultChar && inputLength >= 0
not equal to
inputLength >= 0 && chars[inputLength] == defaultChar?
If It's relevant, this is being run on an 328P Arduino Nano with the old bootloader using IDE 1.8.8
&& is not commutative. It evaluates the left operand first and then stops if the left operand evaluated to 0.
Your original code fails because at some point it evaluates chars[-1] (which causes undefined behaviour if chars is an array). The alternative version does not have that problem because it performs the >= 0 test before using inputLength as an array index.
&& is commutative in the sense that the result of a && b is same as the result of b && a. But the built-in operator && has a short-circuiting behavior. This means that if the result of a && b can be decided by evaluating the first operand alone, the second one is not evaluated.
So when the first operand is chars[inputLength] == defaultChar and inputLength is -1, you enter the territory of undefined behavior which means the behavior of the program is unpredictable. But with the workarounds, you avoid undefined behavior because of the inputLength >= 0 and inputLength < 0 checks and therefore the code works as intended.
As #PeteBecker notes: a() && b() is not commutative if either a() or b() has side effects.

Why does a combined upper and lower bound comparison always evaluate to true? [duplicate]

This question already has answers here:
Comparing a variable to a range of values
(7 answers)
Closed 4 years ago.
Why does the first always evaluate to true? I would expect these two statements to behave identically.
for (int i =0;i<4;++i) (0 < i < 3) ? cout << "True " : cout << "False ";
True True True True
for (int i =0;i<4;++i) (0 < i && i < 3) ? cout << "True " : cout << "False ";
False True True False
The condition 0 < i < 3 is really (0 < i) < 3.
And it doesn't matter if 0 < i is true or not, as the result (0 for false and 1 for true) will always be less than 3.
If you want to make sure i is within a range, you need multiple separate comparisons: 0 < i && i < 3, as you do in the second loop.
Because no combined comparison operator exists in C++. The expression is evaluated as
(0 < i) < 3
but x < 1 evaluates to true/false which evaluates to 1/0 when compared with an int so in the end 0 < 3 is always true and 1 < 3 too.

Explain the following output? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Please explain the output:
#include<iostream.h>
int main()
{
int i= -3, j=2, k=0, m;
m = ++i || ++j && ++k;
cout<< i <<" " << j << " " << k <<" "<<m;
return 0;
}
OUTPUT :
-2 2 0 1
Here's what I thought:
(++i || ++j) && (++k) //Considering the precedence order
++i becomes -2 so first part of OR true, so it won't check 2nd part.
(Thanks Joachim Pileborg for telling me the short circuit evaluation)
So overall, first part of AND is true.
But that is not enough for statement to be true, 2nd part must be true to.
So ++k makes k = 1
Here's where I get it wrong. Why is k not increasing?
whereas, in this case:
#include<iostream.h>
int main()
{
int i= -1, j=2, k=0, m;
m = ++i || ++j && ++k;
cout<< i <<" " << j << " " << k <<" "<<m;
return 0;
}
OUTPUT:
0 3 1 1
I got this one too considering short circuit evaluation.
Let's start with this code snippet
#include<iostream.h>
int main()
{
int i= -3, j=2, k=0, m;
m = ++i || ++j && ++k;
cout<< i <<" " << j << " " << k <<" "<<m;
return 0;
}
It is obvious that m will be have a boolean value converted to int. As ++i is equal to -2 that is unequal to zero then all other expressions will not be evaluated because it is already known that the whole expression is equal to true. So after statement
m = ++i || ++j && ++k;
m is equal to 1 and i is equal to -2 All other variables were not changed.
In this code snippet
#include<iostream.h>
int main()
{
int i= -1, j=2, k=0, m;
m = ++i || ++j && ++k;
cout<< i <<" " << j << " " << k <<" "<<m;
return 0;
}
++i will be equal to 0. So the right operand of operator || will be evaluated. This operand is
++j && ++k
As ++j will be equal to 3 and is not equal to 0 then ++k also will be evaluated and will be equal to 1. As the both operands of operator && is not equal to zero then the result is equal to true
Thus you will get i == 0, j == 3, k == 1, m == 1.
From the C++ Standard
5.14 Logical AND operator
1 The && operator groups left-to-right. The operands are both
contextually converted to bool (Clause 4). The result is true if both
operands are true and false otherwise. Unlike &, && guarantees
left-to-right evaluation: the second operand is not evaluated if the
first operand is false.
5.15 Logical OR operator
1 The || operator groups left-to-right. The operands are both
contextually converted to bool (Clause 4). It returns true if either
of its operands is true, and false otherwise. Unlike |, ||
guarantees left-to-right evaluation; moreover, the second operand is
not evaluated if the first operand evaluates to true.
In logical expressions, such as: ... || ... && ... C++ can omit executing statements that would not change the output value of expression. For example: if it computes first value and it's output is not equal to 0, then expression: true || ... && ... is always true, therefore execution of further expressions is not necessary
Below is your second case:-
int i= -1, j=2, k=0, m;
m = ++i || ++j && ++k;
In
( cond1 || cond2)
expression if cond1 is true then compiler does not go on to check for cond2. It will evaluate cond2 only if cond1 returns false.
So, in second ++i makes first expression to be false and forces compiler to go on to evaluate further whereas in first case first expression returns true.

How || and && works [duplicate]

This question already has answers here:
Logical Operators in C
(8 answers)
Closed 9 years ago.
main( ) {
int i = 4, j = -1, k = 0, w, x, y, z ;
w = i || j || k ;
x = i && j && k ;
y = i || j && k ;
z = i && j || k ;
printf ( "\nw = %d x = %d y = %d z = %d", w, x, y, z ) ;
}
I'm just learning C and I came across this code. I honestly dont know what w, x, y and z are assigned to. Apparently the output is as follows:
w = 1 x = 0 y = 1 z = 1
How is 'w' equal to 1? I dont get it.
|| is the logical OR operator. From C11 s6.5.14 Logical OR operator
The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
...the || operator guarantees left-to-right evaluation;
Applying this to the calculation for w we get
w = i || j || k == (i || j) || k
== (non-zero || non-zero) || 0
== 1 || 0
== 1
Calculations for x, y, z are similar. C11 s6.5.13.3 states that the result from the && operator shall be 0 or 1.
In C there is no "strong" built-in type for Boolean values, so integers are used instead. Results of evaluating logical expressions, such as ones using || and &&, can be assigned to integer variables.
When a value is used in a logical operator, the Boolean interpretation is very straightforward: zeros are interpreted as false, while all non-zero values are interpreted as true.
Now you should be able to figure out the expressions for yourself:
i || j || k evaluates as 1, because i and j are not zeros
i && j && k evaluates as 0, because k is zero,
...and so on.
This is how conceptually it works:
w = i || j || k;
w = 4 || -1 || 0; //values replaced
w = true || 0; //4 || -1 evaluates to true
w = (true); //true is being assigned to integer
w = 1; //0 is false, 1 is for true
It is logical operations.
|| - means logical or, if at least one element is not 0, result is 1, otherwise its 0;
&& - means logical and, if all elements are 1, result is 1, otherwise its 0;
Logical and has higher priority, so:
x = 0 || 4 && 0;
Would be 0, because:
4&&0 = 0
0||0 = 0.
These operators are about full value of number. There are | and & operators connected with bits.
Everything about working and priority is the same, just short example:
uint8_t x = 2 || 4 && 7;
1. 4=00000100 and 7=00000111
00000100
& 00000111
gives:00000100
2. 2=00000010
00000010
| 00000100
gives:00000110, it is 6
I hope it is helpful.
|| is the logical OR.
w = i || j || k;
is equivalent to:
w = (i != 0) || (j != 0) || (k != 0);
i is 4, which explains that w is true (which is evaluated to 1 as C uses integers to deal with booleans).
The same is applicable to && (the logical AND), etc.