How does bitwise operation work on Booleans?
The function you gave does not satisfy the challenge. Right shifting will not do what is asked for. For example, your notNotNot(6,true)
is false
, not true
when put through your function.
Your question is about bitwise operation on a boolean though. Since operators like >>
and <<
work on integers, Javascript first converts the boolean value to an integer. So true
becomes 1 and false
becomes 0. To see this you can shift by zero:
console.log("true is",true >> 0)
console.log("false is", false >> 0)
Using !!
is a handy way to convert anything into a boolean. It takes anything that would be considered equivalent to false (such as 0, null
, undefined
or "") and gives back false
. Similarly anything that is truthy (like 14, "hello", [4], {a:1}) and give back true
. !!
works because the first exclamation mark gives the 'not' of the expression which is always true
or false
, then the second exclamation mark gives the opposite of that (false
or true
).
Getting back to the challenge, it wants to apply the not-operator 'a' times and compare to the 'b' value. So something like this would work:
function notNotNot(a, b) { return !!(a%2 - b); }
console.log("notNotNot(1, true)",notNotNot(1, true));
console.log("notNotNot(2, false)",notNotNot(2, false));
console.log("notNotNot(6, true)",notNotNot(6, true));
Bitwise operators always convert their operands to an integer. So, 4 >> true
is the same as 4 >> 1
which will do a bit shift right by one position
(decimal) 4 = (binary) 100
(binary) 100 >> 1 = (binary) 010
(binary) 010 = (decimal) 2
console.log(4 >> true);
So, using true
or false
is a just a roundabout way to use 1
or 0
.
The notNotNot
function has very simple operation, overall:
a%2
converts the first number into0
for even or1
for odd.>> b
shifts right by either0
positions forfalse
or1
position fortrue
.a
is odd (1) andb
isfalse
=1
- there is zero shifts to the right, so the number remains the same.
a
is odd (1) andb
istrue
=0
- the only set bit
1
is shifted right and discarded.
- the only set bit
a
is even (0) andb
isfalse
=0
- there is zero shifts to the right, so the number remains the same.
a
is even (0) andb
istrue
=0
- the base number is
0
which doesn't have any bits set, so shifting right any amount does not change it.
- the base number is
!!()
converts the result to boolean.
With that said, the solution here is wrong, since notNotNot(2, true)
will produce false
- a
is even and b
is true
. The expectation is that it will produce true
since !!true = true
. The same problem is present for any even number and true
.
It can be easily fixed by using bitwise XOR instead of right shift:
a
is odd (1) andb
isfalse
=1
- both match, so they are flipped to
0
- both match, so they are flipped to
a
is odd (1) andb
istrue
=0
- they don't match, so we get
1
- they don't match, so we get
a
is even (0) andb
isfalse
=0
- both match, so we get
0
- both match, so we get
a
is even (0) andb
istrue
=1
- they don't match, so we get
1
- they don't match, so we get
notNotNot = (a,b) => !!(a%2 ^ b);
console.log("!!true = ", notNotNot(2, true))
console.log("!!!true =", notNotNot(3, true))
console.log("!!false = ", notNotNot(2, false))
console.log("!!!false = ", notNotNot(3, false))
//bonus
console.log("true = ", notNotNot(0, true))
console.log("false = ", notNotNot(0, false))
Just for completeness sake, in case you want a fully bitwise operation:
The modulo operation %2
can be changed to a bitwise AND &1
get the lowest bit. For even numbers, this would yield 0
since you'd be computing
xxx0
&
0001
which is zero. And for odd numbers the same applies but you'd get one as a result:
xxx1
&
0001
So the results of a&1
and a%2
are identical. Furthermore, even though bitwise operations convert the number to a 32-bit signed integer that doesn't matter as the parity would be preserved.
//larger than 31 bits
const largeValue = 2**31 + 1;
//larger than 32 bits
const veryLargeValue = 2**32 + 1
console.log("2**31 + 1 =", largeValue);
console.log("2**32 + 1 =", veryLargeValue);
console.log("2**31 + 1 to 32-bit signed integer =", largeValue | 0);
console.log("2**32 + 1 to 32-bit signed integer = ", veryLargeValue | 0);
const isOddModulo = number =>
console.log(`(${number} % 2) can detect an odd number: ${(number % 2) === 1}`);
const isOddBitwise = number =>
console.log(`(${number} & 1) can detect an odd number: ${(number & 1) === 1}`);
isOddModulo(largeValue);
isOddBitwise(largeValue);
isOddModulo(veryLargeValue);
isOddBitwise(veryLargeValue);