Operadores bit a bit sempre convertem seus operandos em um número inteiro. Então, 4 >> trueé o mesmo 4 >> 1que fará um pequeno deslocamento certo em uma posição
(decimal) 4 = (binary) 100
(binary) 100 >> 1 = (binary) 010
(binary) 010 = (decimal) 2
Portanto, usar trueor falseé apenas uma maneira indireta de usar 1or 0.
A notNotNotfunção possui uma operação muito simples, em geral:
a%2converte o primeiro número em 0para par ou 1ímpar.
>> bmuda para a direita, quer por 0posições falseou 1por true.
aé ímpar (1) e bé false=1
- há zero turnos para a direita, portanto o número permanece o mesmo.
aé ímpar (1) e bé true=0
- o único bit definido
1é deslocado para a direita e descartado.
aé par (0) e bé false=0
- há zero turnos para a direita, portanto o número permanece o mesmo.
aé par (0) e bé true=0
- o número base é o
0que não possui bits definidos; portanto, mudar a quantidade certa para a direita não o altera.
!!() converte o resultado em booleano.
Com isso dito, a solução aqui está errada, pois notNotNot(2, true)produzirá false- aé uniforme e bé true. A expectativa é que ela produza truedesde então !!true = true. O mesmo problema está presente para qualquer número par e true.
Pode ser facilmente corrigido usando o XOR bit a bit em vez do deslocamento à direita:
aé ímpar (1) e bé false=1
- ambos combinam, então eles são virados para
0
aé ímpar (1) e bé true=0
- eles não combinam, então temos
1
aé par (0) e bé false=0
- ambos combinam, então temos
0
aé par (0) e bé true=1
- eles não combinam, então temos
1
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))
Apenas por questões de integridade, caso você queira uma operação totalmente bit a bit:
A operação do módulo %2pode ser alterada para um bit a bit E &1obter o bit mais baixo. Para números pares, isso renderia 0uma vez que você estaria computando
xxx0
&
0001
que é zero. E para números ímpares, o mesmo se aplica, mas você obteria um como resultado:
xxx1
&
0001
Portanto, os resultados a&1e a%2são idênticos. Além disso, embora as operações bit a bit convertam o número em um número inteiro assinado de 32 bits que não importa, pois a paridade seria preservada.
//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);
true=1(decimal) =01(binário) deslocado para a esquerda por um produziria10binário ou2decimal.