Javascript 什么是a^b和(a&b)<&书信电报;1.

Javascript 什么是a^b和(a&b)<&书信电报;1.,javascript,bitwise-operators,Javascript,Bitwise Operators,我在leetcode做这个 请求: 计算两个整数a和b的和,但不允许使用运算符+和- 我无法理解它给出的解决方案 有人能解释一下这个函数是如何工作的吗 以下是JS中的答案: var getSum=函数(a,b){ const Sum=a^b;//我不明白这两行代码是如何工作的 const carry=(a&b)让我们通过示例学习。想象一下a=3和b=5 在二进制表示法中,它们是a=0011和b=0101 异或: a^b是异或运算符。当比较两个位时,如果它们相同,则返回0;如果它们不同,则返回1

我在leetcode做这个

请求:

计算两个整数a和b的和,但不允许使用运算符+和-

我无法理解它给出的解决方案

有人能解释一下这个函数是如何工作的吗

以下是JS中的答案:

var getSum=函数(a,b){
const Sum=a^b;//我不明白这两行代码是如何工作的

const carry=(a&b)让我们通过示例学习。想象一下
a=3
b=5

在二进制表示法中,它们是
a=0011
b=0101

异或:
a^b
是异或运算符。当比较两个位时,如果它们相同,则返回
0
;如果它们不同,则返回
1
01^10=>11

所以当我们做
a^b
时,结果将是
0110

和+SHIFT

a&b
执行逻辑与运算。仅当
a=b=1
时,它才会返回1

在我们的例子中,结果是
0001


所以,XORing的结果是(0011),它实际上是十进制的3。然后我们得到p和q的和

0101
0110
-------
0100
我们通过与5和6求和得到4(二进制中为100),现在如果我们将这个值左移1,我们得到

 0100<<1=1000
所以,做我们得到的第一个XORing

0011
1000
-------
1011
这次的XORing生成了11(1011二进制),所以我们现在执行

0011
1000
-------
0000
对于和3和8,我们得到了所有的零,所以这次左移位运算符也得到了零,因为这里没有1,它可能通过左移位零给我们一个值。 由于进位变量现在为零,我们到了递归的末尾,XORed值将是和,即11(二进制中的1011)


希望你能理解这个过程。通过学习按位运算,你可以学到更多,因为这是机器进行算术运算的方式。

它基本上是在复制

添加2位A和B产生2个输出:一个和和和一个进位,如下所示

╔═══════╤═════════════╗
║ Input │   Output    ║
╠═══╤═══╪═══════╤═════╣
║ A │ B │ carry │ sum ║
╟───┼───┼───────┼─────╢
║ 0 │ 0 │   0   │  0  ║
╟───┼───┼───────┼─────╢
║ 1 │ 0 │   0   │  1  ║
╟───┼───┼───────┼─────╢
║ 0 │ 1 │   0   │  1  ║
╟───┼───┼───────┼─────╢
║ 1 │ 1 │   1   │  0  ║
╚═══╧═══╧═══════╧═════╝
从表中我们得到了输出的逻辑:进位=A和B,和=A或B

也称为无进位加法运算符,由⊕ 带有
+
符号

所以上面的代码片段是这样工作的

const Sum=a^b;              // sum = a xor b = a ⊕ b
const carry=(a&b)<<1;       // carry = 2*(a and b), since we carry to the next bit
if(!carry){
    return Sum;             // no carry, so sum + carry = sum
}
return getSum(Sum,carry);   // a + b = sum + carry
const Sum=a^b;//Sum=a异或b=a⊕ B

const carry=(a&b)
^
是异或,一种按位操作。在单个位上,规则是
0^0=0
0^1=1
1^0=0
,处理多位值时,只需在相应位上扩展执行它。名称是“异或”的缩写,这是因为
A^B
1
当且仅当A或B都是
1
,而不是两者都是。但是,谈论它的另一个名字更有趣,⊕. ⊕ 是+但略有不同。您会注意到⊕ 与添加规则类似:
0+0=0
0+1=1
1+0=1
1+1=10
。⊕ 为+,但
1除外⊕ 1=0
;即,⊕ 是+,除了没有携带。这适用于多个位:
011+001=100
,因为您将
1
从1位携带到2位,然后将
1
再次携带到4位。然后,
011⊕ 001=010
,因为你就是不带


现在,当进行实加法时,什么时候进行?在二进制中,答案很简单:当给定位置有两个
1
时,将
1
带到下一个位置。这很容易理解为按位AND,
&
1&1=1
,否则为
0
。对于
011+001
,加法而不使用携带
011⊕ 001=010
,我们可以知道我们需要把
1
带出这个位置,因为
011&001=001
。在
中的移位(a&b)如果我没有弄错的话,更准确的说法是它复制了全加器,因为函数对自身的递归调用——一个xor加号和一个阶段通向另一个阶段。@Sergiykoldyazhnyy这里的输入只有a和b,这是半加器。全加器的功能是通过递归调用实现的,它给你
a+b+2*carry
。一个真正的全加器需要3个输入
A+b+carryIn=sum+2*carryOut
可能值得指出的是,它是一个每一位同时进行的半加器,不像真值表只显示一个位的位置。请编辑您的问题以澄清您对这些行不了解的原因。您不熟悉w吗关于@Ilmari Karonen的
^
&
可能的重复项,好吧……我将编辑这个问题。这似乎只是讨论特定情况,而不是算法的一般工作原理。我们如何从中知道它适用于所有可能的输入?@ilkkachu您可以尝试不同的输入值,它可能适用于不同的输入我的目标是通过例子来解释算法。
0011
1000
-------
0000
╔═══════╤═════════════╗
║ Input │   Output    ║
╠═══╤═══╪═══════╤═════╣
║ A │ B │ carry │ sum ║
╟───┼───┼───────┼─────╢
║ 0 │ 0 │   0   │  0  ║
╟───┼───┼───────┼─────╢
║ 1 │ 0 │   0   │  1  ║
╟───┼───┼───────┼─────╢
║ 0 │ 1 │   0   │  1  ║
╟───┼───┼───────┼─────╢
║ 1 │ 1 │   1   │  0  ║
╚═══╧═══╧═══════╧═════╝
const Sum=a^b;              // sum = a xor b = a ⊕ b
const carry=(a&b)<<1;       // carry = 2*(a and b), since we carry to the next bit
if(!carry){
    return Sum;             // no carry, so sum + carry = sum
}
return getSum(Sum,carry);   // a + b = sum + carry