Bit yönlü işlem Booleans üzerinde nasıl çalışır?


26

Edabit'teki bu zorlukla karşılaştım ve bu bitsel işlem çözümünü çözemedim.

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

Meydan okuma:

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

Bu operatörün yaptığı bazı araştırmalar yaptım:

En soldaki bitin kopyalarını soldan iterek sağa kaydırır ve en sağdaki bitlerin düşmesine izin verir.

Anladığımı düşündüğüm (örneğin değerlendirdiği ile 5 >> 1aynı ), ancak bunun bir boole ile nasıl çalıştığını göremiyorum? Bildiğim için değerlendirir ve için .0101 >> 10010true1false0


3
Bir boolean sayıya dönüştürülecek ve daha sonra kaydırma gerçekleşecek, böylece true= 1(ondalık) = 01(ikili) bire sola kaydırıldığında 10ikili veya 2ondalık üretilecektir .
VLAZ

Aslında bu çözüm yanlış. Yukarıda belirtilen durumlarda işe yarayacaktır, ancak dikkate notNotNot(2, true)alınacaktır: geri dönecek false, ancak doğru değil ( !!true) olmalı true...
FZs

@FZs doğru. Bu işlev, falseçözümlenecek yalnızca bir tek not sayısını dikkate alır true.
VLAZ

2
Bunun notNotNot = (a,b) => !!((a%2)^b)yerine söyleyebilirim ...
FZs

Neden sadece (a, b) => !!((a + b) % 2)?
Jonas Wilms

Yanıtlar:


16

Verdiğiniz işlev zorluğu tatmin etmiyor. Doğru kaydırma, istenen şeyi yapmayacaktır. Örneğin, notNotNot(6,true)is false, değil truesenin işlevi aracılığıyla koyduğunuzda.

Sorunuz bir boole üzerinde bitsel işlem hakkında. Operatörler gibi yana >>ve <<tamsayılar üzerinde çalışma, JavaScript önce bir tam sayıya boole değeri dönüştürür. Böylece true1 olur ve false0 olur. Bunu görmek için sıfıra kaydırabilirsiniz:

console.log("true is",true >> 0)
console.log("false is", false >> 0)
Yani booleanlarda bitsel işlem gerçekten 0 veya 1'de bitwise işlemdir.

Kullanmak !!, her şeyi bir boole'ye dönüştürmenin kullanışlı bir yoludur. Yanlış (0 null, undefinedveya "" gibi) ile eşdeğer kabul edilecek her şeyi alır ve geri verir false. Benzer şekilde doğru olan herhangi bir şey (14, "merhaba", [4], {a: 1} gibi) ve geri verin true. !!çünkü ilk ünlem işareti her zaman olan ifadenin 'değil' değerini verir, trueya falseda ikinci ünlem işareti bunun ( falseveya true) karşıtını verir .

Zorluğa geri dönersek, operatör olmayan 'a' sürelerini uygulamak ve 'b' değeriyle karşılaştırmak istiyor. Yani böyle bir şey işe yarayacaktır:

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
Bence "meydan okuma" gerçekten bunu kolayca bir döngü olmadan yapabileceğinizi fark istiyor ...
BlueRaja - Danny Pflughoeft

2
@ BlueRaja-DannyPflughoeft gerçekten. Bir döngü olmadan yapmanın en basit yolu, if (a % 2 === 1) return !b else return bancak diğer cevaplarda gösterildiği gibi, dallanma veya döngüler olmadan yapmanın yolları vardır.
VLAZ

evet, ama soru meydan okumayı yapmakla ilgili değildi - operatör ve boole değerlerinin ne kadar bitsel olduğu ile ilgiliydi. Ama cevabımı loop olmayan ve if olmayan bir şekilde güncelledim.
Her Zaman

14

Bitsel işleçler, işlenenlerini her zaman bir tamsayıya dönüştürür. Yani, bir konum sağa biraz kaydırma yapacak 4 >> trueolanla aynı4 >> 1

(decimal) 4 = (binary) 100

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

(binary) 010 = (decimal) 2

console.log(4 >> true);

Yani, kullanma trueveya falsekullanım için sadece bir dolambaçlı bir yoldur 1ya 0.

notNotNotFonksiyon genel olarak, çok basit bir işlem vardır:

  1. a%2ilk sayıyı 0çift ​​veya 1tek için dönüştürür .
  2. >> b0için falseveya 1konumuna göre sağa kaydırır true.
    • atek (1) ve bir bolduğunu false=1
      • sağa sıfır kayma var, bu yüzden sayı aynı kalıyor.
    • atek (1) ve bir bolduğunu true=0
      • ayarlanan tek bit 1sağa kaydırılır ve atılır.
    • aHatta (0) ve bbir false=0
      • sağa sıfır kayma var, bu yüzden sayı aynı kalıyor.
    • aHatta (0) ve bbir true=0
      • taban numarası 0herhangi bir bit ayarlanmamıştır, bu nedenle herhangi bir miktarı doğru kaydırmak onu değiştirmez.
  3. !!() sonucu boole'ye dönüştürür.

Bununla birlikte, buradaki çözüm yanlıştır, çünkü notNotNot(2, true)üretecek false- aeşittir ve beşittir true. O truezamandan beri üreteceği beklentisi !!true = true. Aynı problem çift sayı için de geçerlidir true.

Sağ kaydırma yerine bitsel XOR kullanılarak kolayca sabitlenebilir:

  • atek (1) ve bir bolduğunu false=1
    • her ikisi de eşleşir, böylece 0
  • atek (1) ve bir bolduğunu true=0
    • eşleşmiyorlar, bu yüzden 1
  • aHatta (0) ve bbir false=0
    • her ikisi de eşleşir, 0
  • aHatta (0) ve bbir true=1
    • eşleşmiyorlar, bu yüzden 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))

Tamamen bitmek için, tamamen bitsel bir işlem istiyorsanız:

Modulo işlemi %2bitsel olarak değiştirilebilir VE &1en düşük biti alır. Çift sayılar için, 0hesaplama yapacağınızdan bu elde edilir

xxx0
&
0001

ki bu sıfır. Ve tek sayılar için aynı şey geçerlidir, ancak sonuç olarak bir tane alırsınız:

xxx1
&
0001

Yani sonuçları a&1ve a%2özdeş. Ayrıca, bitsel işlemler sayıyı parite korunacağı için önemli olmayan 32 bit işaretli bir tam sayıya dönüştürse bile .


4

İlk olarak, (a,b) => !!(a%2 >> b)örneklerin sonuçlarıyla eşleşmiyor. Tam olarak ne yaptığını yıkacağım notNotNot(6, true) ➞ true.

  • Yumruk a%2, sadece ageri kalan 2 dönüş bölün. Yani çift sayı için 0, tek sayı için 1 alırız. a = 6 a%2 = 0bu durumda.
  • Sonra 0 >> b1 sayı sağdan kaydırılır, çünkü dediğin gibi truedeğerlendirir 1. Yani anlıyoruz 0 >> 1 = 0.
  • Son olarak !!(0), basit ve bu şekilde parçalanabilir !0 = true, o zaman !true = false.

Bu yüzden sürece bu düşünecek olursak bolduğunu true, her zaman iade alacak false. Diyelim biz = 5, b = true değerlendiren söylüyorlar 5%2 = 1, 1 >> 1 = 0. Mod ( %2) nedeniyle sadece 1 veya 0'a sahip olacağımızı görebilirsiniz (sadece 1 haneli) ve true, elimizde olduğunda daima 1'i kaydırır.

Bu soruna bakmanın basit bir yolu bir isEvenOrNotişlev gibidir. Bu a, kontrol ettiğimiz sayıdır ve bhatta (doğru) olup olmadığını (yanlış) kontrol etmek için bir boole'dir. Bu işe yarıyor çünkü noteklenen her saniye gerçek olacak.

Yani bitwise kullanarak bir çözüm gibi bir şey olabilir: (a,b) => !!(a&1 ^ b). Neden işe yaradığını bozma eğlencesine izin vereceğim! :)

Biraz daha fazla vardiyanın bir boole ile nasıl çalıştığını açıklamaya. Dediğiniz truegibi 1 olacak ve yanlış 0 olacak. Yani örneğinizde gösterildiği gibi, 0101 >> trueaynıdır 0101 >> 1.

Umarım bu yardımcı olur.

Aşağıdakileri bitsel olarak referans olarak kullandım: 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 Her iki boole için de, çift sayıda NOT, orijinal boole ile sonuçlanırken, tek bir NOT sayısı ters boole ile sonuçlanır

Herhangi bir sayının LSB'si sayının tek mi çift mi olduğunu belirtir (0 çift, 1 tek)


1

Görevin olduğunu görüyorum:

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

Benim için neden notnotnotfonksiyon yazdığınızı bilmiyorum , görevin istediği bu değil.

Bu yüzden göreve göre not bir dizi "not" u kabul eden ve değerlendiren bir işlev yaptım .

İlk yol

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

XOr (^) kullanarak ikinci yol

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

@VLAZ tarafından gösterilen Mod (%) kullanarak üçüncü yol

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

Bitsel kullanarak dördüncü yol Ve (&)

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

Ölçek

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

1
Bit manipülasyonu burada yararlıdır, çünkü miktarı umursamıyoruz n- sadece çift ya da tek olup olmadığı, herhangi iki NOT iptal !!!!!bedildiğinden, aynıdır !b. Bu yüzden sadece alırsak bir döngüye ihtiyacımız yok n%2- 1DEĞİL ve 0"aynı tut" için alacağız . Bir sayımız olduğundan, bitsel işlemler yapabiliriz.
VLAZ

Bunu düşünmedim ama haklısın sadece 0 ve 1 ile uğraşıyoruz, teşekkürler, bu yararlı bir yorum :)
SaymoinSam

0

Önce analiz çözümüne izin verir

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

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

Şimdi analiz için (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

Bu, bunun için çalışmadığı anlamına gelir notNotNot(6, true), trueancak mevcut çözüm verir false.

Biz ^(XOR) operatörü düzeltmek için yapabiliriz(a,b) => !!(a%2 ^ b)

Şimdi analiz için (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.

Misal:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.