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.
Related
I am learning Dafny, attempting to write a specification for the hamming weight problem, aka the number of 1 bits in a number. I believe I have gotten the specification correct, but it still doesn't verify. For speed of verification I limited it to 8 bit numbers;
problem definition: https://leetcode.com/problems/number-of-1-bits/
function method twoPow(x: bv16): bv16
requires 0 <= x <= 16
{
1 << x
}
function method oneMask(n: bv16): bv16
requires 0 <= n <= 16
ensures oneMask(n) == twoPow(n)-1
{
twoPow(n)-1
}
function countOneBits(n:bv8): bv8 {
if n == 0 then 0 else (n & 1) + countOneBits(n >> 1)
}
method hammingWeight(n: bv8) returns (count: bv8 )
ensures count == countOneBits(n)
{
count := 0;
var i := 0;
var n' := n;
assert oneMask(8) as bv8 == 255; //passes
while i < 8
invariant 0 <= i <= 8
invariant n' == n >> i
invariant count == countOneBits(n & oneMask(i) as bv8);
{
count := count + n' & 1;
n' := n' >> 1;
i := i + 1;
}
}
I have written the same code in javascript to test the behavior and example the invariant values before and after the loop. I don't seen any problems.
function twoPow(x) {
return 1 << x;
}
function oneMask(n) {
return twoPow(n)-1;
}
function countOneBits(n) {
return n === 0 ? 0 : (n & 1) + countOneBits(n >> 1)
}
function hammingWeight(n) {
if(n < 0 || n > 256) throw new Error("out of range")
console.log(`n: ${n} also ${n.toString(2)}`)
let count = 0;
let i = 0;
let nprime = n;
console.log("beforeloop",`i: ${i}`, `n' = ${nprime}`, `count: ${count}`, `oneMask: ${oneMask(i)}`, `cb: ${countOneBits(n & oneMask(i))}`)
console.log("invariants", i >= 0 && i <= 8, nprime == n >> i, count == countOneBits(n & oneMask(i)));
while (i < 8) {
console.log("");
console.log('before',`i: ${i}`, `n' = ${nprime}`, `count: ${count}`, `oneMask: ${oneMask(i)}`, `cb: ${countOneBits(n & oneMask(i))}`)
console.log("invariants", i >= 0 && i <= 8, nprime == n >> i, count == countOneBits(n & oneMask(i)));
count += nprime & 1;
nprime = nprime >> 1;
i++;
console.log('Afterloop',`i: ${i}`, `n' = ${nprime}`, `count: ${count}`, `oneMask: ${oneMask(i)}`, `cb: ${countOneBits(n & oneMask(i))}`)
console.log("invariants", i >= 0 && i <= 8, nprime == n >> i, count == countOneBits(n & oneMask(i)));
}
return count;
};
hammingWeight(128);
All invariants evaluate as true. I must be missing something. it says invariant count == countOneBits(n & oneMask(i) as bv8); might not be maintained by the loop. Running the javascript shows that they are all true. Is it due to the cast of oneMask to bv8?
edit:
I replaced the mask function with one that didn't require casting and that still not resolve the problem.
function method oneMaskOr(n: bv8): bv8
requires 0 <= n <= 8
ensures oneMaskOr(n) as bv16 == oneMask(n as bv16)
{
if n == 0 then 0 else (1 << (n-1)) | oneMaskOr(n-1)
}
One interesting thing I found is that it shows me a counter example where it has reached the end of the loop and the final bit of the input variable n is set, so values 128 or greater. But when I add an assertion above the loop that value equals the count at the end of the loop it then shows me the another value of n.
assert 1 == countOneBits(128 & OneMaskOr(8)); //counterexample -> 192
assert 2 == countOneBits(192 & OneMaskOr(8)); //counterexample -> 160
So it seems like it isn't evaluating the loop invariant after the end of loop? I thought the whole point of the invariants was to evaluate after the end of loop.
Edit 2:
I figured it out, apparently adding the explicit decreases clause to the while loop fixed it. I don't get it though. I thought Dafny could figure this out.
while i < 8
invariant 0 <= i <= 8
invariant n' == n >> i
invariant count == countOneBits(n & oneMask(i) as bv8);
decreases 8 - i
{
I see one line in the docs for loop termination saying
If the decreases clause of a loop specifies *, then no termination check will be performed. Use of this feature is sound only with respect to partial correctness.
So is if the decreases clause is missing does it default to *?
After playing around, I did find a version which passes though it required reworking countOneBits() so that its recursion followed the order of iteration:
function countOneBits(n:bv8, i: int, j:int): bv8
requires i ≥ 0 ∧ i ≤ j ∧ j ≤ 8
decreases 8-i {
if i == j then 0
else (n&1) + countOneBits(n >> 1, i+1, j)
}
method hammingWeight(n: bv8) returns (count: bv8 )
ensures count == countOneBits(n,0,8)
{
count ≔ 0;
var i ≔ 0;
var n' ≔ n;
//
assert count == countOneBits(n,0,i);
//
while i < 8
invariant 0 ≤ i ≤ 8;
invariant n' == n >> i;
invariant count == countOneBits(n,0,i);
{
count ≔ (n' & 1) + count;
n' ≔ n' >> 1;
i ≔ i + 1;
}
}
The intuition here is that countOneBits(n,i,j) returns the number of 1 bits between i (inclusive) and j (exclusive). This then reflects what the loop is doing as we increase i.
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.
The model is optimizing the costs of Machines in Cell layout design
regarding the duplication and subcontracting.
Mod Const. is,
forall (k in 1..Cells, i in 1..nbMachines, j in 1..nbComps)
{
if (U[i][j][k] == 1 && A[k][i] < ((D[k][j]*S[k][j])*52))
DN[i][j][k] == 1;
SC[i][j][k] == 0;
INT[i][j][k] == 0;
}
forall (k in 1..Cells, i in 1..nbMachines, j in 1..nbComps)
{
if (V[i][j][k] == 1 && A[k][i] >= ((D[k][j]*S[k][j])*52))
DN[i][j][k] == 0;
SC[i][j][k] == 1;
INT[i][j][k] == 1;}
U , V are extracted in previous steps, A, D, S are input data.
The variables reqd. are DN, SC and INT.
Errors are those expressions are cannot be extracted, U, V are unbounded,
Please help in this regard,
Since U and V are decision variables, you should not write:
if (U[i][j][k] == 1 && A[k][i] < ((D[k][j]*S[k][j])*52))
DN[i][j][k] == 1;
Instead write:
((U[i][j][k] == 1) && (A[k][i] <= -1+((D[k][j]*S[k][j])*52)))
=> (DN[i][j][k] == 1);
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
Can I do this in C++?
if (4<5<6)
cout<<"valid"<<endl;
i.e a double comparison? Since I know that I can
bool a;
a = 1+2<3+4<5>6;//etc
Yes, you can do it, but it won't be what you expect. It's parsed as
if ( (4<5) < 6 )
which yields
if ( 1 < 6 )
because 4<5 evaluates to true which is promoted to 1, which yields, obviously, true.
You'll need
if ( (4<5) && (5<6) )
Also, yes, you can do
a = 1+2<3+4<5>6;
but that as well is parsed as
a = ((1+2)<((3+4)<5))>6;
which will evaluate to false since (1+2)<((3+4)<5) yields a boolean, which is always smaller than 6.
It compiles but won't do what you expect -
if( 4 < 5 < 2)
same as
if( (4 < 5) < 2)
same as
if( (1 < 2) ) //1 obtained from cast to boolean
which is of course true, even though I imagine you were expecting something quite different.
It may be clumsy but this will work:
int i, j, k;
i = 4; j = 5; k = 6;
if ( (i < j) && (j < k) )
{
cout << "Valid!" << endl;
}