i&0xFF vs我256为负数

时间:2019-11-01 18:14:10

标签: javascript bitwise-operators modulo bitwise-and

我想知道为什么当i为0或正数时(i%256)和(i&0xFF)是相同的,但是当i为负数时为何完全不同。

用于测试的代码:

i = -100
while (i < 100) {
    if (!((i & 0xFF) == (i % 256))) console.log(i);
    i++;
}

这是为什么?

3 个答案:

答案 0 :(得分:1)

首先是运算符的摘要:

&是按位和运算符。

  • 例如,对于4位正数,
0110 (6)
0100 (4) &
-------
0100 (4)
  • 例如,对于4位负数(2的补码),
1010 (-6)
1100 (-4) &
-------
1000 (-8)

%是模运算符。 x % y大致意味着x - parseInt(x / y) * x

  • 例如,对于一个正数,8 % 3 === 2
  • 例如,对于负数,-8 % 3 === -2

现在回答问题

对于我们的解释,我们简单地使用i & 0b0011 (3)1 % 0b0100 (4)而不是255和256。对于此问题,这是等效的,因为二进制中的256是{{1 }}和10000...的二进制形式是0xff

  • 对于小于4的正数:01111...i & 0b0011都将返回1 % 0b0100

i

2 % 4 = 4
  • 对于大于或等于4的正数:0010 (2) 0011 (3) & ------- 0010 (2) i & 0b0011

1 % 0b0100

7 % 4 = 3

答案 1 :(得分:1)

负数以two's complement的形式表示,即-100的二进制表示为

(2**32 - 100).toString(2) = 11111111111111111111111110011100

添加0xff将得到10011100,即156

模运算%定义为

IF a % b == r  THEN a == b * q + r for some q

qr始终有两个选择,余数为正和负。例如,使用7 % 3

 7 = 3 * 2 + 1
 7 = 3 * 3 - 2

负数相同,-7 % 3

 -7 = 3 * (-2) - 1
 -7 = 3 * (-3) + 2

对于正数,所有语言都选择正余数。对于负数,选择因语言而异。例如在python中,余数始终为正,所以

 -7 % 3 = 2   # python

JavaScript选择负数,所以在JS

 -7 % 3 = -1  // javascript

类似地,对于-100 % 256

-100 = 256 * ( 0) - 100
-100 = 256 * (-1) + 156

在python中,余数为156(因此与& FF相匹配),在javascript中为-100

答案 2 :(得分:0)

发生这种情况是因为这些操作是不同的,所以您不问为什么2+2等于2*2,而是2+3!= 2*3,对吗?

无论如何,主要的问题是数字的按位表示不是1:1关系,不同的数字可以具有相同的表示(有关详细信息,请检查Signed versus Unsigned Integers

因此,%模运算符采用除法余数并且具有符号,所以

console.log(-100 % 256); // shows -100 which is true

按位&与物理位一起工作,它不了解符号位的设置,因此,如果我们查看-100的按位表示-它是10011100并且同时按位表示为156

console.log((0b10011100)); // unsigned 156
console.log((0b10011100 << 24 >> 24)); // signed -100