ブール値に対してビット演算はどのように機能しますか?


26

私はEdabitでこの課題に遭遇し、このビット単位の操作ソリューションを解決できませんでした。

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

チャレンジ:

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

私はその演算子を研究しました:

左端のビットのコピーを左から押し込むことにより右にシフトし、右端のビットが落ちるようにします。

私は理解したと思います(たとえばが5 >> 10101 >> 1評価されるのと同じです0010)が、それがブール値でどのように機能するかわかりませんか?私が知っているtrueと評価された1falseすると0


3
ブール値を数値に変換するだけでシフトが発生するため、true= 1(10進数)= 01(2 進数)を1つ左にシフトすると、102進数または210進数が生成されます。
VLAZ

実際、このソリューションは正しくありません。上記のケースでは機能しますが、notNotNot(2, true)次の点を考慮してください:戻りますがfalse、真ではありません(!!true)である必要がありtrueます...
FZ

正しい@FZs。関数は、falseに解決するaの奇数のnotのみを考慮しtrueます。
VLAZ

2
notNotNot = (a,b) => !!((a%2)^b)代わりに言います...
FZ

なぜ(a, b) => !!((a + b) % 2)ですか?
ジョナスウィルムス

回答:


16

あなたが与えた機能は挑戦を満足させません。右シフトは求められていることを行いません。たとえば、あなたのnotNotNot(6,true)isはfalsetrueあなたの関数を通過するときではありません。

あなたの質問は、ブール値のビット演算についてです。演算子は整数のよう>><<動作するため、JavaScriptは最初にブール値を整数に変換します。これtrueが1にfalseなり、0になります。これを確認するには、0シフトできます。

console.log("true is",true >> 0)
console.log("false is", false >> 0)
したがって、ブール値のビット演算は、実際には0または1のビット演算です。

を使用する!!と、何でもブール値に変換できます。それは(そのような0と偽と同等と考えられるものを取るnullundefinedまたは「」)とバックを提供しますfalse。同様に、真実であるもの(14、 "hello"、[4]、{a:1}など)を返しtrueます。!!最初の感嘆符が常にtrueor である式の「否定」を与えるので、false2番目の感嘆符はそれとは反対の(falseまたはtrue)を与えるため、機能します。

課題に戻り、非演算子を 'a'回適用し、 'b'値と比較します。したがって、次のようなものが機能します:

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
「チャレンジ」は、ループなしでこれを簡単に実行できることを実現することを本当に望んでいると思います...
BlueRaja-Danny Pflughoeft

2
@ BlueRaja-DannyPflughoeft確かに。ループなしでそれを行う最も簡単な方法はif (a % 2 === 1) return !b else return bありますが、他の回答に示されているように、分岐やループなしでそれを行う方法があります。
VLAZ

はい、しかし問題は挑戦をすることではありませんでした-それはどのようにビットごとの演算子とブール値についてでした。しかし、私はループとnon-ifの方法で私の答えを更新しました。
常に

14

ビット演算子は、常にそのオペランドを整数に変換します。つまり、1ポジション右に少しシフトするのと4 >> true同じ4 >> 1です。

(decimal) 4 = (binary) 100

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

(binary) 010 = (decimal) 2

console.log(4 >> true);

したがって、trueor falseを使用することは、1or を使用するための単なる迂回的な方法0です。

このnotNotNot関数は、全体的に非常に単純な操作です。

  1. a%2最初の数値0を偶数または1奇数に変換します。
  2. >> b0位置falseまたはの1位置だけ右にシフトしますtrue
    • a奇数(1)でbあり、false=1
      • 右へのシフトはゼロなので、数値は同じままです。
    • a奇数(1)でbあり、true=0
      • 設定された唯一のビット1は右にシフトされて破棄されます。
    • aは偶数(0)でbあり、false=0
      • 右へのシフトはゼロなので、数値は同じままです。
    • aは偶数(0)でbあり、true=0
      • 基数は0ビットが設定されていないため、右にシフトしても変化しません。
  3. !!() 結果をブール値に変換します。

そうは言っているので、ここでの解決策は、間違ってnotNotNot(2, true)生成されますfalse- aでもあるとbされますtrue。期待はそれがそれtrue以来生産すること!!true = trueです。同じ問題が偶数との両方に存在しますtrue

これは、右シフトの代わりにビットごとのXORを使用することで簡単に修正できます。

  • a奇数(1)でbあり、false=1
    • 両方が一致するため、反転します 0
  • a奇数(1)でbあり、true=0
    • それらは一致しないので、 1
  • aは偶数(0)でbあり、false=0
    • 両方が一致するので、 0
  • aは偶数(0)でbあり、true=1
    • それらは一致しないので、 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))

完全を期すために、完全にビット単位の操作が必要な場合は、次のようにします。

モジュロ演算%2はビット単位に変更&1でき、最下位ビットを取得できます。偶数の場合、0計算を行うため、これは

xxx0
&
0001

これはゼロです。そして奇数の場合も同じことが当てはまりますが、結果として次のようになります。

xxx1
&
0001

したがって、a&1およびの結果a%2は同じです。さらに、ビット単位の演算では数値が32ビットの符号付き整数に変換されますが、パリティは保持されるため問題ではありません。


4

まず、(a,b) => !!(a%2 >> b)例の結果と一致しません。私はそれを使って何をしているかを正確に分析しnotNotNot(6, true) ➞ trueます。

  • a%2、単にa2で除算して残りを返します。したがって、偶数の場合は0、奇数の場合は1になります。a = 6 a%2 = 0この場合。
  • 次に0 >> b、あなたが言ったようにがにtrue評価されるので、右から1つの数値をシフトします1。だから私たちは得る0 >> 1 = 0
  • 最後には!!(0)、シンプルで、かつ、そのように分けることができ!0 = true、その後、!true = false

だから私たちは、限り、この考える場合btrue、我々は常に返されますfalse。a = 5、b = trueと評価する5%2 = 1とし1 >> 1 = 0ます。mod(%2)が原因で、1または0(1桁のみ)のみが存在し、trueがある場合は常に1からシフトオフすることがわかります。

この問題を確認する簡単な方法は、isEvenOrNot関数のようなものです。だから、a私たちがチェックされている番号で、bそれも(真)かどう確認するか、いなくても(偽)するブール値です。not追加された1秒ごとがtrueになるため、これは機能します。

したがって、ビットワイズを使用したソリューションは次のようになります(a,b) => !!(a&1 ^ b)。なぜそれが機能するのかを分解する楽しみをあなたに与えましょう!:)

シフトがブールでどのように機能するかを説明するもう少し。つまりtrue、あなたが言ったように1になり、falseは0になります。したがって、例に示すように、はと0101 >> true同じ0101 >> 1です。

これがお役に立てば幸いです。

以下をbitwiseのリファレンスとして使用しました: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

注:どちらのブール値でも、NOTの数が偶数の場合は元のブール値になり、NOTの数が奇数の場合は反対のブール値になります。

任意の数のLSBは、その数が奇数か偶数かを決定します。(0偶数、1奇数)


1

あなたの仕事は次のとおりです:

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

あなたがなぜnotnotnot私のために関数を書いているのか、私にはわかりません。

だから私はその機能を作ったタスクに従って not 、いくつかの「nots」を受け入れ、それらを評価するました。

最初の方法

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

XOr(^)を使用した2番目の方法

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

@VLAZが指すMod(%)を使用する3番目の方法

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

ビットごとのAnd(&)を使用する4番目の方法

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

テスト

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

1
ここではビット操作が役立ちます。量は気にしませんn。2つのNOTは相殺されるため、偶数か奇数かだけです。したがって!!!!!b、と同じ!bです。我々だけ取ればそこで我々は、ループを必要としないn%2-私たちは取得したい1しないためと0、「同じことを続ける」ため。数があるので、ビット単位の演算を実行できます。
VLAZ

さて、私はそれについては考えていませんでしたが、あなたが正しいのは0と1だけを扱っているということです。ありがとうございます。これは便利なコメントです:)
SaymoinSam

0

最初に分析ソリューションを見てみましょう

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

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

今の分析 (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

つまり、これは機能していませんnotNotNot(6, true)true、現在の解決策はfalseです。

^(XOR)演算子を使用して、それを正しくすることができます(a,b) => !!(a%2 ^ b)

今の分析 (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.

例:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.