我想知道为什么当i为0或正数时(i%256)和(i&0xFF)是相同的,但是当i为负数时为何完全不同。
用于测试的代码:
i = -100
while (i < 100) {
if (!((i & 0xFF) == (i % 256))) console.log(i);
i++;
}
这是为什么?
答案 0 :(得分:1)
&
是按位和运算符。
0110 (6)
0100 (4) &
-------
0100 (4)
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
。
01111...
和i & 0b0011
都将返回1 % 0b0100
。 i
2 % 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
q
和r
始终有两个选择,余数为正和负。例如,使用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