按位运算如何处理布尔值?

kia*_*ott 31 javascript

我在 Edabit 上遇到了这个挑战,无法解决这个按位运算的解决方案。

notNotNot = (a,b) => !!(a%2 >> b)
Run Code Online (Sandbox Code Playgroud)

挑战:

//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
Run Code Online (Sandbox Code Playgroud)

我做了一些研究,该操作员:

通过从左侧推入最左侧位的副本来向右移动,并让最右侧位脱落。

我认为我理解(​​例如,5 >> 10101 >> 1它的计算结果相同0010),但我看不到布尔值是如何工作的?我知道true的计算结果为1,并false0

Alw*_*ing 20

The function you gave does not satisfy the challenge. Right shifting will not do what is asked for. For example, your notNotNot(6,true) is false, not true when put through your function.

Your question is about bitwise operation on a boolean though. Since operators like >> and << work on integers, Javascript first converts the boolean value to an integer. So true becomes 1 and false becomes 0. To see this you can shift by zero:

console.log("true is",true >> 0)
console.log("false is", false >> 0)
Run Code Online (Sandbox Code Playgroud)
So bitwise operation on booleans is really just bitwise operation on either 0 or 1.

Using !! is a handy way to convert anything into a boolean. It takes anything that would be considered equivalent to false (such as 0, null, undefined or "") and gives back false. Similarly anything that is truthy (like 14, "hello", [4], {a:1}) and give back true. !! works because the first exclamation mark gives the 'not' of the expression which is always true or false, then the second exclamation mark gives the opposite of that (false or true).

Getting back to the challenge, it wants to apply the not-operator 'a' times and compare to the 'b' value. So something like this would work:

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));
Run Code Online (Sandbox Code Playgroud)

  • 我认为“挑战”真的希望你意识到你可以轻松地做到这一点而无需循环...... (9认同)
  • 确实是@BlueRaja-DannyPflughoeft。在没有循环的情况下执行此操作的最简单方法是“if (a % 2 === 1) return !b else return b”,但如其他答案所示,有一些方法可以在不分支或循环的情况下执行此操作。 (2认同)

VLA*_*LAZ 14

按位运算符始终将其操作数转换为整数。所以,4 >> true4 >> 1将右移一个位置相同

(decimal) 4 = (binary) 100

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

(binary) 010 = (decimal) 2
Run Code Online (Sandbox Code Playgroud)

因此,使用true或者false是只是一种迂回的方式来使用10

notNotNot功能操作非常简单,总体来说:

  1. a%2将第一个数字转换0为偶数或1奇数。
  2. >> b右移0位置 forfalse1position for true
    • a是奇数 (1) 并且bfalse=1
      • 向右移动零,因此数字保持不变。
    • a是奇数 (1) 并且btrue=0
      • 唯一的设置位1被右移并丢弃。
    • a是偶数 (0) 并且bfalse=0
      • 向右移动零,因此数字保持不变。
    • a是偶数 (0) 并且btrue=0
      • 基数是0没有设置任何位的,因此右移任何数量都不会改变它。
  3. !!() 将结果转换为布尔值。

话虽如此,这里的解决方案是错误的,因为notNotNot(2, true)will generate false- ais even 并且bis true。期望它会产生true!!true = true。任何偶数和 都存在同样的问题true

它可以通过使用按位异或而不是右移轻松修复:

  • a是奇数 (1) 并且bfalse=1
    • 两者都匹配,所以它们被翻转到 0
  • a是奇数 (1) 并且btrue=0
    • 他们不匹配,所以我们得到 1
  • a是偶数 (0) 并且bfalse=0
    • 两者匹配,所以我们得到 0
  • a是偶数 (0) 并且btrue=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))
Run Code Online (Sandbox Code Playgroud)

为了完整起见,如果您想要完全按位运算:

模运算%2可以更改为按位并&1获得最低位。对于偶数,这会产生,0因为你要计算

xxx0
&
0001
Run Code Online (Sandbox Code Playgroud)

这是零。对于奇数,同样适用,但您会得到一个结果:

xxx1
&
0001
Run Code Online (Sandbox Code Playgroud)

所以结果a&1a%2是相同的。此外,即使按位运算将数字转换为 32 位有符号整数也无关紧要,因为奇偶校验将被保留。