按位运算如何在布尔值上工作



我在 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 >> 1与计算结果为00100101 >> 1相同),但我看不出它如何与布尔值一起工作?我知道true评估为1false评估为0.

您给出的功能不能满足挑战。右移不会做所要求的事情。例如,您的notNotNot(6,true)false,而不是通过您的函数时true

不过,您的问题是关于布尔值上的按位运算。由于像>><<这样的运算符处理整数,Javascript首先将布尔值转换为整数。所以true变成 1,false变成 0。 要查看这一点,您可以按零移动:

console.log("true is",true >> 0)
console.log("false is", false >> 0)
因此,布尔值上的按位运算实际上只是 0 或 1 上的按位运算。

使用!!是将任何内容转换为布尔值的便捷方法。它接受任何被认为等同于 false 的东西(例如 0、nullundefined或 ")并返回false。同样,任何真实的东西(如14,"hello",[4],{a:1})并回馈true!!工作是因为第一个感叹号给出的表达式总是truefalse的"not",然后第二个感叹号给出与此相反的(falsetrue)。

回到挑战,它希望应用非运算符"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));

按位运算符始终将其操作数转换为整数。因此,4 >> true4 >> 1相同,后者会向右移动一个位置

(decimal) 4 = (binary) 100
(binary) 100 >> 1 = (binary) 010
(binary) 010 = (decimal) 2

console.log(4 >> true);

因此,使用truefalse只是使用10的一种迂回方式。

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

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

话虽如此,这里的解决方案是错误的,因为notNotNot(2, true)会产生false-a是均匀的,btrue的。期望它将产生自!!true = true年以来的true.任何偶数和偶数都存在相同的问题true

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

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

只是为了完整起见,如果您需要完全按位操作:

取模运算%2可以更改为按位 AND&1得到最低位。对于偶数,这将产生0,因为您将计算

xxx0
&
0001

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

xxx1
&
0001

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

//larger than 31 bits
const largeValue = 2**31 + 1;
//larger than 32 bits
const veryLargeValue = 2**32 + 1
console.log("2**31 + 1 =", largeValue);
console.log("2**32 + 1 =", veryLargeValue);
console.log("2**31 + 1 to 32-bit signed integer =", largeValue | 0);
console.log("2**32 + 1 to 32-bit signed integer = ", veryLargeValue | 0);
const isOddModulo = number => 
console.log(`(${number} % 2) can detect an odd number: ${(number % 2) === 1}`);
const isOddBitwise = number => 
console.log(`(${number} & 1) can detect an odd number: ${(number & 1) === 1}`);
isOddModulo(largeValue);
isOddBitwise(largeValue);
isOddModulo(veryLargeValue);
isOddBitwise(veryLargeValue);

首先,(a,b) => !!(a%2 >> b)与示例的结果不匹配。我将使用notNotNot(6, true) ➞ true准确分解它正在做什么。

  • 拳头a%2,只需得到a除以 2 返回余数。因此,偶数为 0,奇数为 1。 在这种情况下a = 6a%2 = 0
  • 然后0 >> b从右边移开 1 个数字,因为正如您所说true计算结果为1.所以我们得到0 >> 1 = 0.
  • 最后!!(0),很简单,可以这样分解,!0 = true,然后!true = false

所以如果我们考虑一下,只要btrue,我们总会得到false的回报。假设我们有 a = 5,b = true 评估为5%2 = 11 >> 1 = 0。你可以看到,由于 mod (%2) 我们只会有 1 或 0(只有 1 位数字),而 true 在我们拥有它时将始终移出 1。

看待这个问题的简单方法就像一个isEvenOrNot函数。所以a是我们正在检查的数字,b是一个布尔值,用于检查它是偶数(真)还是偶数(假)。这是有效的,因为添加的每一秒not都是真的。

因此,使用按位的解决方案可以是这样的:(a,b) => !!(a&1 ^ b). 我会让你享受分解它为什么有效的乐趣!:)

进一步解释移位如何使用布尔值工作。所以true如你所说将是 1,假将是 0。因此,如您的示例所示,0101 >> true0101 >> 1相同。

我希望这有所帮助。

我使用以下内容作为按位的参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

(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 导致原始布尔值 奇数个 NAT 导致相反的布尔值

任何数字的LSB决定了该数字是奇数还是偶数。(0 偶数,1 奇数)

我看到你的任务是:

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

我不知道你为什么要写notnotnot函数 对我来说,这不是任务所要求的。

因此,根据任务,我使该功能not它接受一些"不"并对其进行评估。

第一种方式

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

使用 XOr(^) 的第二种方式

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

第三种使用Mod(%)的方法由@VLAZ指出

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

第四种方式使用按位 And(&)

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

测试

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

让我们先分析解决方案

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

相关内容

最新更新