当我在这里运行此代码时:
console.log(255<<24==0xff000000)
我得到的是假而不是真的。这是为什么?
因为 JavaScript 数字是 IEEE-754 双精度浮点数,而不是 32 位整数。一个大的正数(十进制 4,278,190,080)也是如此0xff000000
,而不是一个负数,因为它是一个有符号的 32 位整数。
当你这样做<<
时,被移动的数字(在你的情况下为 255)会临时转换为有符号的 32 位整数,以便进行位移:
000000000000000000000000011111111 ^\ / | \----- 有效位----/ +------- 符号位
当我们向左移动 24 位时,符号位中会出现 1 位:
11111111000000000000000000000000 ^\ / | \----- 有效位----/ +------- 符号位
...因此结果最终为负数,并变回负数 IEEE-754 数(-16,777,216 十进制)。-16,777,216 不等于 4,278,190,080。
(IEEE-754 双精度浮点数的范围大于 32 位有符号整数的范围。我不太确定为什么我觉得这是相关的,但我确实如此,所以我想我会把它留在答案中...)
这样看。这对您来说应该很直观:
255<<24 == 0xff000000<<0 // Returns true
位运算符适用于整数而不是数字类型。将其视为等同于其他语言中的类型转换,您碰巧将较大大小的数字放入较小的数字中,而您会丢失东西...
由于采用了浮点格式,Javascript 牺牲了精度以允许更大的数字。
所以 Javascript 会失去 0xff000000 的精度,就像 255 一样。
如 TJ 所述,javascript 中的按位运算将数字转换为有符号的32 位整数,因此您只有 31 位可以安全地与十六进制文字进行比较。如果您想保留您真正想要的无符号数(而不是将您的十六进制文字转换为相同的负数),请执行以下操作:
255 * (1 << 24) == 0xff000000
0xff000000
不指定 32 位整数的位,而是以十六进制为基数的实数。例如0xff000000000000000000000
是4.932417344027687e+27
除了>>>
给出操作数 int32 语义外,所有按位运算都>>>
给出 uint32 语义。
因此,您可以将| 0
其用作一种int
声明或(int)
强制转换:
255 << 24 == (0xff000000 | 0)
true