Bagaimana cara operasi bitwise bekerja pada Boolean?

26

Saya menemukan tantangan ini pada Edabit dan tidak dapat menyelesaikan solusi operasi bitwise ini.

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

Tantangan:

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

Saya melakukan riset bahwa operator itu:

Bergeser ke kanan dengan mendorong salinan bit paling kiri dari kiri, dan biarkan bit paling kanan jatuh.

Saya rasa saya mengerti (misalnya 5 >> 1sama dengan 0101 >> 1yang mengevaluasi 0010), tapi saya tidak bisa melihat bagaimana itu bekerja dengan boolean? Saya tahu truemengevaluasi ke 1dan falseke 0.

kiabbott
sumber
3
Boolean hanya akan ditransformasikan ke angka dan kemudian pergeseran akan terjadi, jadi true= 1(desimal) = 01(biner) bergeser ke kiri oleh orang akan menghasilkan 10biner atau 2desimal.
VLAZ
Sebenarnya, solusi ini salah. Dalam kasus-kasus yang disebutkan di atas, itu akan berhasil, tetapi pertimbangkan notNotNot(2, true): itu akan kembali false, tetapi tidak tidak benar ( !!true) harus true...
FZs
@ FZ itu benar. Fungsi ini hanya akan mempertimbangkan jumlah ganjil dari not falseuntuk diselesaikan true.
VLAZ
2
notNotNot = (a,b) => !!((a%2)^b)Sebagai gantinya saya akan mengatakan ...
FZ
Kenapa tidak adil (a, b) => !!((a + b) % 2)?
Jonas Wilms

Jawaban:

16

Fungsi yang Anda berikan tidak memuaskan tantangan. Pergeseran yang benar tidak akan melakukan apa yang diminta. Sebagai contoh, Anda notNotNot(6,true)yaitu false, tidak trueketika dimasukkan melalui fungsi Anda.

Pertanyaan Anda adalah tentang operasi bitwise pada boolean. Karena operator menyukai >>dan <<bekerja pada bilangan bulat, Javascript terlebih dahulu mengubah nilai boolean menjadi bilangan bulat. Jadi truemenjadi 1 dan falsemenjadi 0. Untuk melihat ini, Anda dapat menggeser nol:

console.log("true is",true >> 0)
console.log("false is", false >> 0)
Jadi operasi bitwise pada booleans sebenarnya hanya operasi bitwise pada 0 atau 1.

Menggunakan !!adalah cara praktis untuk mengubah apa pun menjadi boolean. Dibutuhkan apa pun yang akan dianggap setara dengan false (seperti 0 null,, undefinedatau "") dan memberikan kembali false. Demikian pula segala sesuatu yang benar (seperti 14, "halo", [4], {a: 1}) dan berikan kembali true. !!bekerja karena tanda seru pertama memberikan 'tidak' dari ekspresi yang selalu trueatau false, maka tanda seru kedua memberikan kebalikan dari itu ( falseatau true).

Kembali ke tantangan, ia ingin menerapkan waktu bukan operator dan membandingkannya dengan nilai 'b'. Jadi sesuatu seperti ini akan berhasil:

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

Selalu belajar
sumber
9
Saya pikir "tantangan" benar-benar ingin Anda sadari bahwa Anda dapat dengan mudah melakukan ini tanpa loop ...
BlueRaja - Danny Pflughoeft
2
@ BlueRaja-DannyPflughoeft memang. Cara paling sederhana untuk melakukannya tanpa loop adalah if (a % 2 === 1) return !b else return btetapi ada seperti yang ditunjukkan dalam jawaban lain, ada cara untuk melakukannya tanpa bercabang atau loop.
VLAZ
ya, tapi pertanyaannya bukan tentang melakukan tantangan - itu tentang bagaimana bitwise nilai operator dan boolean. Tapi saya sudah memperbarui jawaban saya dengan cara non-loop dan non-jika.
Selalu Belajar
14

Operator bitwise selalu mengonversi operan mereka ke integer. Jadi, 4 >> truesama seperti 4 >> 1yang akan melakukan sedikit bergeser ke kanan dengan satu posisi

(decimal) 4 = (binary) 100

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

(binary) 010 = (decimal) 2

console.log(4 >> true);

Jadi, menggunakan trueatau falsehanya jalan memutar untuk menggunakan 1atau 0.

The notNotNotfungsi memiliki operasi yang sangat sederhana, secara keseluruhan:

  1. a%2mengubah angka pertama menjadi 0genap atau 1ganjil.
  2. >> bbergeser ke kanan dengan 0posisi untuk falseatau 1posisi untuk true.
    • aganjil (1) dan bis false=1
      • tidak ada pergeseran ke kanan, jadi angkanya tetap sama.
    • aganjil (1) dan bis true=0
      • bit yang diset hanya 1digeser ke kanan dan dibuang.
    • abahkan (0) dan badalah false=0
      • tidak ada pergeseran ke kanan, jadi angkanya tetap sama.
    • abahkan (0) dan badalah true=0
      • nomor dasar adalah 0yang tidak memiliki bit yang ditetapkan, jadi menggeser ke kanan jumlah apa pun tidak mengubahnya.
  3. !!() mengubah hasilnya menjadi boolean.

Dengan itu, solusi di sini salah, karena notNotNot(2, true)akan menghasilkan false- abahkan dan bada true. Harapannya adalah bahwa itu akan menghasilkan truesejak itu !!true = true. Masalah yang sama hadir untuk nomor genap dan true.

Itu dapat dengan mudah diperbaiki dengan menggunakan XOR bitwise bukannya shift kanan:

  • aganjil (1) dan bis false=1
    • keduanya cocok, jadi mereka membalik ke 0
  • aganjil (1) dan bis true=0
    • mereka tidak cocok, jadi kita dapatkan 1
  • abahkan (0) dan badalah false=0
    • keduanya cocok, jadi kita dapatkan 0
  • abahkan (0) dan badalah true=1
    • mereka tidak cocok, jadi kita dapatkan 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))

Hanya demi kelengkapan, jika Anda menginginkan operasi bitwise sepenuhnya:

Operasi modulo %2dapat diubah menjadi bitwise DAN &1mendapatkan bit terendah. Untuk bilangan genap, ini akan menghasilkan 0karena Anda akan menghitung

xxx0
&
0001

yang merupakan nol. Dan untuk bilangan ganjil hal yang sama berlaku tetapi Anda akan mendapatkan hasilnya:

xxx1
&
0001

Jadi hasilnya a&1dan a%2identik. Lebih lanjut, meskipun operasi bitwise mengubah angka menjadi integer bertanda 32-bit yang tidak masalah karena paritas akan dipertahankan.

VLAZ
sumber
4

Pertama, (a,b) => !!(a%2 >> b)tidak cocok dengan hasil contoh. Saya akan memecah apa yang dilakukan dengan menggunakan notNotNot(6, true) ➞ true.

  • Fist a%2, cukup abagi dengan 2 kembalikan sisanya. Jadi kita akan mendapatkan 0 untuk bilangan genap dan 1 untuk bilangan ganjil. a = 6 a%2 = 0pada kasus ini.
  • Kemudian 0 >> bgeser 1 angka dari kanan karena seperti yang Anda katakan truebernilai 1. Jadi kita dapatkan 0 >> 1 = 0.
  • Terakhir !!(0), sederhana, dan dapat dipecah seperti itu !0 = true, lalu !true = false.

Jadi jika kita memikirkan ini selama bini true, kita akan selalu kembali false. Katakanlah kita memiliki = 5, b = true mengevaluasi untuk 5%2 = 1, 1 >> 1 = 0. Anda dapat melihat karena mod ( %2) kita hanya akan memiliki 1 atau 0 (hanya pernah memiliki 1 digit) dan true akan selalu mematikan 1 ketika kita memilikinya.

Cara sederhana untuk melihat masalah ini seperti sebuah isEvenOrNotfungsi. Begitu ajuga nomor yang kami periksa dan bmerupakan boolean untuk memeriksa apakah itu genap (benar) atau bahkan genap (salah). Ini berfungsi karena setiap detik yang notditambahkan akan benar.

Jadi solusi menggunakan bitwise bisa menjadi sesuatu seperti: (a,b) => !!(a&1 ^ b). Saya akan membiarkan Anda bersenang-senang menguraikan mengapa itu berhasil! :)

Sedikit lagi menjelaskan bagaimana shift bekerja dengan boolean. Jadi trueseperti yang Anda katakan akan menjadi 1 dan false akan menjadi 0. Jadi seperti yang ditunjukkan dalam contoh Anda, 0101 >> truesama dengan 0101 >> 1.

Saya harap ini membantu.

Saya menggunakan yang berikut sebagai referensi untuk bitwise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

domsim1
sumber
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 Untuk salah satu boolean, jumlah TIDAK yang rata menghasilkan boolean asli, jumlah TIDAK yang aneh menghasilkan boolean yang berlawanan

LSB dari nomor mana pun menentukan apakah nomor tersebut ganjil atau genap. (0 genap, 1 ganjil)

Stephen Duffy
sumber
1

Saya melihat bahwa tugas Anda adalah:

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

Saya tidak tahu mengapa Anda menulis notnotnotfungsi untuk saya bukan itu tugasnya.

Jadi sesuai dengan tugas saya membuat fungsi not yang menerima sejumlah "tidak" dan mengevaluasi mereka.

Cara pertama

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

Cara kedua menggunakan XOr (^)

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

Cara ketiga menggunakan Mod (%) yang ditunjukkan oleh @VLAZ

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

Cara keempat menggunakan bitwise And (&)

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

Uji

not(0)
//> false 
not(1)
//> true
not(2)
//> false
not(515)
//> true
SaymoinSam
sumber
1
Manipulasi bit berguna di sini, karena kami tidak peduli tentang jumlahnya n- hanya apakah itu genap atau ganjil, karena ada dua TIDAK yang dibatalkan, begitu !!!!!bjuga dengan !b. Karenanya kita tidak perlu loop jika kita hanya mengambil n%2- kita akan mendapatkan 1untuk TIDAK dan 0untuk "tetap sama". Karena kita memiliki nomor, kita bisa melakukan operasi bitwise
VLAZ
Ya saya tidak memikirkan hal itu tetapi Anda benar, kami hanya berurusan dengan 0 dan 1, terima kasih, ini adalah komentar yang berguna :)
SaymoinSam
0

Mari kita analisis solusi

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

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

Sekarang analisis untuk (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

Thats di sarana ini tidak bekerja untuk notNotNot(6, true)adalah truetetapi solusi saat memberikan false.

Kami dapat Anda ^(XOR) operator untuk membuatnya Seperti benar(a,b) => !!(a%2 ^ b)

Sekarang analisis untuk (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.

Contoh:

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

Eklavya
sumber