Don't understand why (5 | -2) > 0 is False where (5 or -2) > 0 is True
What is the difference between or
and |
?
or
is a logical or and |
is a bitwise or logical inclusive or.
The logical or
The logical or in python returns the first value that is true.
Example:
>>> None or False or 5
5
>>> -5 or 2
-5
The bitwise or logical inclusive or
The bitwise or logical inclusive or is represented by the |
operator in python and creates a number where all bits are set that are set in at least one of the given numbers.
Example:
- 2 is in binary
0010
- 4 is in binary
0100
A logical or between the two results in 0110
which is 6.
>>> 2 | 4
6
How a negative number is stored is generally implementation specific. However on most systems a negative number is stored by creating the two's complement of the positive number by inverting each bit and adding 1.
That number in bitwise ore two any other number still results in a negative number:
>>> -5 | 2
-5
Neither of the two solves your problem
While using
(vals[1] or vals[0]) > 0
seems to work, it fails when you flip the values:
>>> vals = [2, -5]
>>> (vals[1] or vals[0]) > 0
False
You should check both values seperatly
>>> vals = [-5, 2]
>>> vals[0] > 0 or vals[1] > 0
True
For a larger input this may be inconvenient. You should use any with a generator expression:
>>> any(x > 0 for x in vals)
True
You want the any
function:
>>> any(x > 0 for x in vals)
x | y
computes the bitwise OR
of the two values, while x or y
evaluates to the first "truthy" value. In both cases, the result is then compared to 0
: (x or y) > 0
and (x | y) > 0
.
What you want to compare each value to zero (as necessary), with
vals[0] > 0 or vals[1] > 0
If you had three values, you'd write
vals[0] > 0 or vals[1] > 0 or vals[2] > 0
The any
function generalizes this to a list of any size, without the need to decide how many terms to or
together based on the size of the list.
To answer this question, I have to explain about Two's Complement.
BINARY REPRESENTATION OF NUMBERS
So you know how internally, an integer like 5 is represented as a binary string
00000000000000000000000000000101
How do you imagine you'd represent a negative number?
Well, here's what we want to do:
Addition should work the same with negative numbers and positive numbers; i.e. you do the same steps to add 4 + 9 as 4 + -9.
Integer overflow shouldn't break mathematics; i.e.
MAX_VALUE + 1 == MIN_VALUE
,MIN_VALUE - 1 == MAX_VALUE
So what we do is called "Two's Complement."
TWO'S COMPLEMENT
To represent a negative number, take its absolute value, bitflip every bit, and add 1.
So if the positive number is 5
00000000000000000000000000000101
the negative number -5 is
11111111111111111111111111111011
Essentially, this means we pick the number 01111111111111111111111111111111
to be the largest positive number, and all numbers after that are negative.
SO WHAT DOES (5 | -2) MEAN?
The |
is the bitwise or operator. Given two numbers, it takes every bit and or's them together, constructing a new number where a digit is 1 if the digit in that position in wither or both of the two original numbers is 1, and 0 otherwise. The calculation looks like this:
5 -> 00000000000000000000000000000101
| -2 -> 11111111111111111111111111111110
---- --------------------------------
11111111111111111111111111111111 -> -1
So as you can see, 5 | -2 = -1 < 0.
WHAT ABOUT (5 or -2)?
The "or" operator takes two values, casts them to booleans and or's them together. This is important: it doesn't or the values, it returns the first value that is "truthy" -- in other words, if you put it in an if statement, it would run.
The only integer that isn't "truthy" is 0. Therefore (5 or -2) returns the first non-zero integer of 5 and 2, which is 5 > 0. So 5 or -2 = 5 > 0.