Swift中&+运算符的JavaScript等价实现及djbHash结果不一致问题
JavaScript与Swift的djbHash结果不一致问题解决
问题根源
Swift的djbHash实现有两个关键特性是JS版本没处理的:
- Swift的
&+是溢出加法:当计算结果超出当前Int类型的位数(64位系统下是64位有符号整数)时,会自动截断保留低64位,不会抛出溢出错误。 - JS的Number是双精度浮点数,无法精确表示超过2^53的整数;即使改用BigInt,也不会自动处理溢出,会保留完整的大整数结果,自然和Swift的溢出截断结果不一致。
修正后的JavaScript实现
要模拟Swift的64位有符号整数溢出行为,我们可以用BigInt计算,并手动处理溢出截断:
function djbHash(string) { let h = 5381n; const uint64Mod = 2n ** 64n; const int64Max = 2n ** 63n - 1n; for (let i = 0; i < string.length; i++) { const ascii = BigInt(string.charCodeAt(i)); // 执行哈希计算后,对2^64取模模拟64位溢出 h = ((h << 5n) + h + ascii) % uint64Mod; } // 将无符号64位结果转换为有符号64位整数(匹配Swift的Int类型) if (h > int64Max) { h -= uint64Mod; } // 如需转为Number(仅当结果在JS安全整数范围内时建议),可使用Number(h) return h; }
验证结果
用字符串“QHChLUHDMNh5UTBUcgtLmlPziN42”测试,修正后的JS代码会返回357350748206983768n,和Swift的结果完全一致。
内容的提问来源于stack exchange,提问作者j.doe
相关产品推荐
相关产品推荐

