Come funziona l'operazione bit per bit su booleani?


26

Mi sono imbattuto in questa sfida su Edabit e non sono riuscito a elaborare questa soluzione operativa bit a bit.

notNotNot = (a,b) => !!(a%2 >> b)

La sfida:

//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

Ho fatto alcune ricerche che quell'operatore:

Sposta a destra spingendo le copie del bit più a sinistra da sinistra e lascia cadere i bit più a destra.

Che penso di aver capito (es. Lo 5 >> 1stesso di 0101 >> 1chi valuta 0010), ma non riesco a vedere come funziona con un valore booleano? So che truevaluta da 1e falseper 0.


3
Un booleano sta per essere trasformato in un numero e quindi si verificherà lo spostamento, quindi true= 1(decimale) = 01(binario) spostato a sinistra di uno produrrebbe 10binario o 2decimale.
VLAZ,

In realtà, questa soluzione non è corretta. Nei casi sopra menzionati funzionerà, ma considera notNotNot(2, true): tornerà false, ma non è vero ( !!true) dovrebbe essere true...
FZ

@FZs che è corretto. La funzione prenderà in considerazione solo un numero dispari di not su falsea cui risolvere true.
VLAZ,

2
Direi notNotNot = (a,b) => !!((a%2)^b)invece ...
FZ,

Perché non solo (a, b) => !!((a + b) % 2)?
Jonas Wilms,

Risposte:


16

La funzione che hai assegnato non soddisfa la sfida. Il giusto spostamento non farà ciò che viene richiesto. Ad esempio, lo notNotNot(6,true)è false, non truequando viene messo in pratica.

La tua domanda riguarda l'operazione bit a bit su un valore booleano. Poiché agli operatori piacciono >>e <<lavorano su numeri interi, Javascript prima converte il valore booleano in un numero intero. Quindi truediventa 1 e falsediventa 0. Per vederlo puoi spostarti di zero:

console.log("true is",true >> 0)
console.log("false is", false >> 0)
Quindi l'operazione bit a bit su booleani è un'operazione a bit su 0 o 1.

L'utilizzo !!è un modo pratico per convertire qualsiasi cosa in un valore booleano. Prende tutto ciò che sarebbe considerato equivalente a falso (come 0 null, undefinedo "") e restituisce false. Allo stesso modo tutto ciò che è vero (come 14, "ciao", [4], {a: 1}) e restituire true. !!funziona perché il primo punto esclamativo dà il "non" dell'espressione che è sempre trueo false, quindi il secondo punto esclamativo dà il contrario di quello ( falseo true).

Tornando alla sfida, vuole applicare i tempi "a" non operatore e confrontarli con il valore "b". Quindi qualcosa del genere funzionerebbe:

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));


9
Penso che la "sfida" voglia davvero farti capire che puoi farlo facilmente senza un ciclo ...
BlueRaja - Danny Pflughoeft

2
@ BlueRaja-DannyPflughoeft davvero. Il modo più semplice per farlo senza un ciclo è if (a % 2 === 1) return !b else return bma lì, come mostrato in altre risposte, ci sono modi per farlo senza ramificazioni o anelli.
VLAZ

sì, ma la domanda non era di fare la sfida - si trattava di come operatori bit per bit e valori booleani. Ma ho aggiornato la mia risposta con un metodo non-loop e non-if.
Impara sempre il

14

Gli operatori bit a bit convertono sempre i loro operandi in un numero intero. Quindi, 4 >> trueè lo stesso 4 >> 1che farà un po 'di spostamento a destra di una posizione

(decimal) 4 = (binary) 100

(binary) 100 >> 1 = (binary) 010

(binary) 010 = (decimal) 2

console.log(4 >> true);

Quindi, usare trueo falseè solo un modo per usare rotatoria 1o 0.

La notNotNotfunzione ha un funzionamento molto semplice, nel complesso:

  1. a%2converte il primo numero in 0pari o 1dispari.
  2. >> bsi sposta a destra di entrambe le 0posizioni per falseo 1posizione per true.
    • aè dispari (1) ed bè false=1
      • ci sono zero spostamenti a destra, quindi il numero rimane lo stesso.
    • aè dispari (1) ed bè true=0
      • l'unico bit impostato 1viene spostato a destra e scartato.
    • aè pari (0) ed bè false=0
      • ci sono zero spostamenti a destra, quindi il numero rimane lo stesso.
    • aè pari (0) ed bè true=0
      • il numero di base è 0che non ha nessun bit impostato, quindi spostando a destra qualsiasi importo non lo cambia.
  3. !!() converte il risultato in booleano.

Detto questo, la soluzione qui è sbagliata, poiché notNotNot(2, true)produrrà false- aè pari ed bè true. L'aspettativa è che produrrà da trueallora !!true = true. Lo stesso problema è presente per qualsiasi numero pari e true.

Può essere facilmente risolto usando XOR bit a bit invece di spostamento a destra:

  • aè dispari (1) ed bè false=1
    • entrambi corrispondono, quindi vengono visualizzati 0
  • aè dispari (1) ed bè true=0
    • non corrispondono, quindi otteniamo 1
  • aè pari (0) ed bè false=0
    • entrambi corrispondono, quindi arriviamo 0
  • aè pari (0) ed bè true=1
    • non corrispondono, quindi otteniamo 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))

Solo per completezza, nel caso in cui si desideri un'operazione completamente bit a bit:

L'operazione modulo %2può essere modificata in modo bit a bit E &1ottenere il bit più basso. Per i numeri pari, ciò produrrebbe 0dal momento che dovresti calcolare

xxx0
&
0001

che è zero. E per i numeri dispari vale lo stesso ma ne otterrai uno come risultato:

xxx1
&
0001

Quindi i risultati di a&1e a%2sono identici. Inoltre, anche se le operazioni bit a bit convertono il numero in un numero intero con segno a 32 bit che non ha importanza in quanto la parità verrebbe mantenuta.


4

Innanzitutto, (a,b) => !!(a%2 >> b)non corrisponde ai risultati degli esempi. Analizzerò esattamente cosa sta facendo usando notNotNot(6, true) ➞ true.

  • Pugno a%2, semplicemente adividi per 2 restituisci il resto. Quindi avremo 0 per un numero pari e 1 per un numero dispari. a = 6 a%2 = 0in questo caso.
  • Quindi 0 >> bspostare 1 numero fuori da destra perché, come hai detto, truevaluta 1. Quindi otteniamo 0 >> 1 = 0.
  • Infine !!(0), è semplice e può essere suddiviso in questo modo !0 = true, quindi !true = false.

Quindi, se pensiamo a questo il tempo che bè true, ci sarà sempre ottenere tornati false. Diciamo che abbiamo a = 5, b = true valutazione a 5%2 = 1, 1 >> 1 = 0. Puoi vedere a causa del mod ( %2) avremo sempre solo 1 o 0 (sempre e solo 1 cifra) e true sposterà sempre l'1 quando ce l'abbiamo.

Un modo semplice per esaminare questo problema è come una isEvenOrNotfunzione. Quindi aè il numero che stiamo controllando ed bè un valore booleano per verificare se è pari (vero) o addirittura (falso). Questo funziona perché ogni secondo notaggiunto sarà vero.

Quindi, una soluzione che utilizza bit per bit potrebbe essere qualcosa del tipo: (a,b) => !!(a&1 ^ b). Ti farò divertire a scomporre perché funziona! :)

Un po 'di più per spiegare come funziona il turno con un booleano. Quindi, truecome hai detto, sarà 1 e false sarà 0. Quindi, come mostrato nel tuo esempio, 0101 >> trueè lo stesso di 0101 >> 1.

Spero che questo possa essere d'aiuto.

Ho usato quanto segue come riferimento per bit a bit: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators


1
(a%2)  //ignore all but the least significant bit (LSB)
(a%2 >> b )  //if TRUE,  shifts right, resolves to 0
               //if FALSE, no shift,     resolves to LSB

// 0 and LSB are both integers so convert to boolean by using logical/boolean NOT
!(a%2 >> b ) //resolves to the boolean which it is NOT
!!(a%2 >> b ) //resolves to the boolean which it is NOT NOT

NB Per entrambi i valori booleani, un numero pari di NOT comporta il valore booleano originale, mentre un numero dispari di NOT comporta il valore booleano opposto

L'LSB di qualsiasi numero determina se il numero è pari o dispari (0 pari, 1 dispari)


1

Vedo che il tuo compito è:

/* Create a function where given n number of "not",
   evaluate whether it's true or false.*/

Non so perché tu stia scrivendo una notnotnotfunzione per me che non è ciò che il compito richiede.

Quindi, in base al compito, ho realizzato quella funzione not che accetta un numero di "not" e le valuta.

Il primo modo

function not(n) {
  return Boolean(n - n - 1);
}

Il secondo modo usando XOr (^)

function not(n) {
  return Boolean(bool ^ (bool - 1));
}

Il terzo modo usando Mod (%) indicato da @VLAZ

function not(n) {
  return Boolean(n % 2);
}

Il quarto modo usando bitwise And (&)

function not(n) {
  return Boolean(n & 1);
}

Test

not(0)
//> false 
not(1)
//> true
not(2)
//> false
not(515)
//> true

1
La manipolazione dei bit è utile qui, poiché non ci importa della quantità n- solo se è pari o dispari, poiché due NOT NON si annullano, quindi !!!!!bè lo stesso di !b. Quindi non abbiamo bisogno di un ciclo se prendiamo semplicemente n%2- otterremmo 1per NOT e 0per "mantenerlo uguale". Dato che abbiamo un numero, possiamo semplicemente fare operazioni bit per bit.
VLAZ,

Beh, non ci ho pensato, ma hai ragione, abbiamo a che fare solo con 0 e 1, grazie, questo è un commento utile :)
SaymoinSam

0

Consente prima la soluzione di analisi

notNotNot(oddNumber, true)   false
notNotNot(evenNumber, true)  true

notNotNot(oddNumber, false)   true
notNotNot(evenNumber, false)  false

Ora analizza il per (a,b) => !!(a%2 >> b)

a%2 == 0  even number
a%2 == 1  odd number

// For a%2 == 0

a%2 >> b  if b is true   0 >> 1  0   // Not working
a%2 >> b  if b is false  0 >> 0  0


// For a%2 == 1

a%2 >> b  if b is true   1 >> 1  0
a%2 >> b  if b is false  1 >> 0  1

Questo significa che non funziona per notNotNot(6, true)questo, truema la soluzione attuale dà false.

Possiamo voi ^(XOR) operatore per renderlo corretto Mi piace(a,b) => !!(a%2 ^ b)

Ora analizza il per (a,b) => !!(a%2 ^ b)

a%2 == 0  even number
a%2 == 1  odd number

// For a%2 == 0

a%2 ^ b  if b is true   0 ^ 1  1   // Now working
a%2 ^ b  if b is false  0 ^ 0  0


// For a%2 == 1

a%2 ^ b  if b is true   1 ^ 1  0
a%2 ^ b  if b is false  1 ^ 0  1

!(a%2 ^ b) use `!` to make int as boolean but solution result will reversed then
!!(a%2 ^ b) use `!` again to reversed it again and make it correct.

Esempio:

notNotNot = (a,b) => !!(a%2 ^ b);

console.log("!!!!true = ", notNotNot(4, true))
console.log("!!!!false = ", notNotNot(4, false))
console.log("!!!true =", notNotNot(3, true))
console.log("!!!false = ", notNotNot(3, false))

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.