我在 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
与计算结果为0010
的0101 >> 1
相同),但我看不出它如何与布尔值一起工作?我知道true
评估为1
,false
评估为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、null
、undefined
或 ")并返回false
。同样,任何真实的东西(如14,"hello",[4],{a:1})并回馈true
。!!
工作是因为第一个感叹号给出的表达式总是true
或false
的"not",然后第二个感叹号给出与此相反的(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));
按位运算符始终将其操作数转换为整数。因此,4 >> true
与4 >> 1
相同,后者会向右移动一个位置
(decimal) 4 = (binary) 100
(binary) 100 >> 1 = (binary) 010
(binary) 010 = (decimal) 2
console.log(4 >> true);
因此,使用true
或false
只是使用1
或0
的一种迂回方式。
notNotNot
功能的操作非常简单,总的来说:
a%2
将第一个数字转换为偶数的0
或奇数的1
。>> b
向右移动0
位置表示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
,它没有任何位设置,因此向右移动任何数量都不会改变它。
- 基数是
!!()
将结果转换为布尔值。
话虽如此,这里的解决方案是错误的,因为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
可以更改为按位 AND&1
得到最低位。对于偶数,这将产生0
,因为您将计算
xxx0
&
0001
为零。对于奇数,同样适用,但结果你会得到一个:
xxx1
&
0001
因此,a&1
和a%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 = 6
a%2 = 0
。 - 然后
0 >> b
从右边移开 1 个数字,因为正如您所说true
计算结果为1
.所以我们得到0 >> 1 = 0
. - 最后
!!(0)
,很简单,可以这样分解,!0 = true
,然后!true = false
。
所以如果我们考虑一下,只要b
true
,我们总会得到false
的回报。假设我们有 a = 5,b = true 评估为5%2 = 1
,1 >> 1 = 0
。你可以看到,由于 mod (%2
) 我们只会有 1 或 0(只有 1 位数字),而 true 在我们拥有它时将始终移出 1。
看待这个问题的简单方法就像一个isEvenOrNot
函数。所以a
是我们正在检查的数字,b
是一个布尔值,用于检查它是偶数(真)还是偶数(假)。这是有效的,因为添加的每一秒not
都是真的。
因此,使用按位的解决方案可以是这样的:(a,b) => !!(a&1 ^ b)
. 我会让你享受分解它为什么有效的乐趣!:)
进一步解释移位如何使用布尔值工作。所以true
如你所说将是 1,假将是 0。因此,如您的示例所示,0101 >> true
与0101 >> 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))