Me deparei com esse desafio no Edabit e não consegui resolver essa solução de operação bit a bit.
notNotNot = (a,b) => !!(a%2 >> b)
O desafio:
//Something which is not true is false, but something which is not not true is true!
//Create a function where given n number of "not", evaluate whether it's true or false.
//Examples:
notNotNot(1, true) ➞ false
// Not true
notNotNot(2, false) ➞ false
// Not not false
notNotNot(6, true) ➞ true
// Not not not not not not true
Eu fiz algumas pesquisas que esse operador:
Desloca para a direita empurrando cópias do bit mais à esquerda da esquerda e deixe os bits mais à direita caírem.
Acho que entendi (por exemplo, o 5 >> 1
mesmo 0101 >> 1
que avalia 0010
), mas não consigo ver como isso funciona com um booleano? Eu sei que true
avalia para 1
e false
para 0
.
javascript
Kiabbott
fonte
fonte
true
=1
(decimal) =01
(binário) deslocado para a esquerda por um produziria10
binário ou2
decimal.notNotNot(2, true)
: retornaráfalse
, mas não é verdadeiro (!!true
) deve sertrue
...false
para resolvertrue
.notNotNot = (a,b) => !!((a%2)^b)
...(a, b) => !!((a + b) % 2)
?Respostas:
A função que você deu não satisfaz o desafio. A mudança para a direita não fará o que é pedido. Por exemplo, você
notNotNot(6,true)
éfalse
, nãotrue
quando realiza sua função.Sua pergunta é sobre a operação bit a bit em um booleano. Como os operadores gostam
>>
e<<
trabalham com números inteiros, o Javascript primeiro converte o valor booleano em um número inteiro. Então,true
torna-se 1 efalse
torna - se 0. Para ver isso, você pode mudar por zero:Usar
!!
é uma maneira prática de converter qualquer coisa em um booleano. Ele pega qualquer coisa que seja considerada equivalente a false (como 0null
,undefined
ou "") e devolvefalse
. Da mesma forma, qualquer coisa que seja verdadeira (como 14, "olá", [4], {a: 1}) e devolvatrue
.!!
funciona porque o primeiro ponto de exclamação fornece o 'não' da expressão que é sempretrue
oufalse
, então o segundo ponto de exclamação fornece o oposto disso (false
outrue
).Voltando ao desafio, ele deseja aplicar o não operador 'a' vezes e comparar com o valor 'b'. Então, algo assim funcionaria:
fonte
if (a % 2 === 1) return !b else return b
mas, como mostrado em outras respostas, existem maneiras de fazê-lo sem ramificações ou loops.Operadores bit a bit sempre convertem seus operandos em um número inteiro. Então,
4 >> true
é o mesmo4 >> 1
que fará um pequeno deslocamento certo em uma posiçãoPortanto, usar
true
orfalse
é apenas uma maneira indireta de usar1
or0
.A
notNotNot
função possui uma operação muito simples, em geral:a%2
converte o primeiro número em0
para par ou1
ímpar.>> b
muda para a direita, quer por0
posiçõesfalse
ou1
portrue
.a
é ímpar (1) eb
éfalse
=1
a
é ímpar (1) eb
étrue
=0
1
é deslocado para a direita e descartado.a
é par (0) eb
éfalse
=0
a
é par (0) eb
étrue
=0
0
que 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 eb
étrue
. A expectativa é que ela produzatrue
desde então!!true = true
. O mesmo problema está presente para qualquer número par etrue
.Pode ser facilmente corrigido usando o XOR bit a bit em vez do deslocamento à direita:
a
é ímpar (1) eb
éfalse
=1
0
a
é ímpar (1) eb
étrue
=0
1
a
é par (0) eb
éfalse
=0
0
a
é par (0) eb
étrue
=1
1
Apenas por questões de integridade, caso você queira uma operação totalmente bit a bit:
A operação do módulo
%2
pode ser alterada para um bit a bit E&1
obter o bit mais baixo. Para números pares, isso renderia0
uma vez que você estaria computandoque é zero. E para números ímpares, o mesmo se aplica, mas você obteria um como resultado:
Portanto, os resultados
a&1
ea%2
sã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.Mostrar snippet de código
fonte
Em primeiro lugar,
(a,b) => !!(a%2 >> b)
não corresponde aos resultados dos exemplos. Vou detalhar exatamente o que está fazendo usandonotNotNot(6, true) ➞ true
.a%2
, bastaa
dividir por 2 e retornar o restante. Portanto, obteremos 0 para um número par e 1 para um número ímpar.a = 6
a%2 = 0
nesse caso.0 >> b
desloque 1 número da direita, porque, como você disse,true
avalia1
. Então chegamos0 >> 1 = 0
.!!(0)
, é simples, e pode ser dividido da seguinte forma,!0 = true
e, em seguida!true = false
.Portanto, se pensarmos sobre isso enquanto
b
fortrue
, sempre teremos retornofalse
. Vamos dizer que temos a = 5, b = true avaliar para5%2 = 1
,1 >> 1 = 0
. Você pode ver que, devido ao mod (%2
), teremos apenas 1 ou 0 (apenas 1 dígito) e true sempre desativará o 1 quando o tivermos.Uma maneira simples de encarar esse problema é como uma
isEvenOrNot
função. Assima
é o número que estamos verificando eb
é um booleano para verificar se é par (verdadeiro) ou não (falso). Isso funciona porque cada segundonot
adicionado será verdadeiro.Então, uma solução usando bit a bit poderia ser algo como:
(a,b) => !!(a&1 ^ b)
. Vou deixar você se divertir ao descobrir por que funciona! :)Um pouco mais sobre como o shift funciona com um booleano. Então,
true
como você disse, será 1 e false será 0. Portanto, como mostrado no seu exemplo,0101 >> true
é o mesmo que0101 >> 1
.Eu espero que isso ajude.
Usei o seguinte como referência para bit a bit: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
fonte
NB Para qualquer booleano, um número par de NOTs resulta no booleano original e um número ímpar de NOTs resulta no booleano oposto
O LSB de qualquer número determina se o número é ímpar ou par. (0 par, 1 ímpar)
fonte
Vejo que sua tarefa é:
Não sei por que você está escrevendo uma
notnotnot
função para mim que não é o que a tarefa pede.Então, de acordo com a tarefa, criei essa função
not
que aceita vários "nots" e os avalia.A primeira maneira
A segunda maneira usando XOr (^)
A terceira maneira usando Mod (%) apontado por @VLAZ
A quarta maneira usando E bit a bit (&)
Teste
fonte
n
- apenas se é par ou ímpar, já que dois NOTs não são cancelados,!!!!!b
é o mesmo que!b
. Portanto, não precisamos de um loop se apenas fizermosn%2
- teríamos1
NOT e0
por "manteremos o mesmo". Como temos um número, podemos apenas fazer operações bit a bit.Deixa a solução de análise primeiro
Agora analise o para
(a,b) => !!(a%2 >> b)
Thats meios isto não está trabalhando para
notNotNot(6, true)
setrue
mas solução atual dáfalse
.Podemos
^
operador (XOR) para corrigi-lo(a,b) => !!(a%2 ^ b)
Agora analise o para
(a,b) => !!(a%2 ^ b)
Exemplo:
fonte