逻辑移位的工作方式不同于其他语言。
var value = 1543812808507000000
var lowBits = value >>> 0
这是JavaScript代码。结果是3804366080。但是当我们用java或c开发此逻辑时,结果是3804366016。
哪个是正确的? javascript如何进行逻辑移位?
答案 0 :(得分:3)
MAX_SAFE_INTEGER常数的值为9007199254740991(9,007,199,254,740,991或〜9四千万分之一)。该数字背后的原因是,JavaScript使用IEEE 754中指定的双精度浮点格式数字,并且只能安全地表示-(2 53 -1)和2 53 < / sup>-1。
已经在注释中指出,您输入的1543812808507000000大于最大的安全整数。
因此,四舍五入发生在JavaScript端。
相比之下,C和Java都使用(精确)积分数学(低于C版本):
unsigned long long n = 1543812808507000000ULL;
n &= 0x00000000ffffffffULL;
printf("%llu\n", n);
替代计算:
n %= 0x0000000100000000ULL;
因此,C / Java输出在数学上是正确的。
您也很有可能使用浮点数学在C语言中产生相同的结果:
uint64_t n64 = 1543812808507000000ULL;
double d = n64; // on conversion, rounding occurs!
uint32_t n32 = d; // back to 32 bit, most significant bits dropped
printf("%lu\n", (unsigned long)n32);
出于完整性考虑:IEEE754描述了不同的舍入算法,并且C标准不强制要求特定的算法-实际上,它甚至根本不强制要求IEEE754。但是由于JS和C都直接使用相同的基础硬件(并且所有现代硬件都遵循IEEE754并具有相同的默认舍入),所以这没有实际意义。
如果您对演员表感到疑惑:uint32_t
很可能被typedef
编辑为unsigned int
,但不一定(可以是{{1} }甚至unsigned long
都符合C标准。但是,对于unsigned short
,C要求覆盖一个范围,这样我们至少需要 32位,因此通过强制转换并使用unsigned long
格式说明符,可以避免由于以下原因导致的未定义行为:格式说明符和数据类型不匹配,而不会改变结果。