You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python实现的Jenkins one_at_a_time哈希与JS版本输出一致

问题根因

两段代码结果不一致来自三个核心差异:

  • 字符编码处理不一致:JS的charCodeAt返回字符的UTF-16编码单元值,你原Python代码中ord(char.encode("utf-8"))逻辑错误,对于多字节的UTF-8字符只会取第一个字节的编码值,和JS的输入处理逻辑不匹配。
  • 移位操作行为不一致:JS的>>是有符号右移,会保留符号位;你原Python代码中的右移是对32位无符号整数做算术右移,和JS的移位结果完全不同。
  • 输出格式不一致:Python的hex()函数会返回带0x前缀的字符串,且不会自动补前导零到8位,和JStoString(16)的输出格式不匹配。

修正后的Python代码(完全对齐JS输出)

import ctypes

def calculateChecksum(keyString: str):
    # Credits(modified code): Bob Jenkins
    # 对齐魔改JS版本的Jenkins one-at-a-time哈希实现
    hash = 0
    for char in keyString:
        # 对齐JS charCodeAt的UTF-16码点取值(BMP字符下等价于Unicode码点)
        hash += ord(char)
        hash &= 0xFFFFFFFF
        hash += hash << 10
        hash &= 0xFFFFFFFF
        # 模拟JS的32位有符号右移6位
        signed_hash = ctypes.c_int32(hash).value
        hash ^= signed_hash >> 6
        hash &= 0xFFFFFFFF
    hash += hash << 3
    hash &= 0xFFFFFFFF
    # 模拟JS的32位有符号右移11位
    signed_hash = ctypes.c_int32(hash).value
    hash ^= signed_hash >> 11
    hash &= 0xFFFFFFFF
    hash += hash << 15
    hash &= 0xFFFFFFFF
    # 对齐JS toString(16)输出格式:去除0x前缀,补前导零到8位
    return hex(hash)[2:].zfill(8)

JS代码和维基示例不匹配的原因

你使用的JS代码是魔改后的版本,并非Jenkins one-at-a-time哈希的标准实现,改动了两个核心逻辑:

  1. 输入处理从标准的字节序列改为UTF-16编码单元
  2. 移位操作使用有符号右移,而非标准实现的无符号右移
    因此JS代码的结果和维基百科的标准实现示例不一致,你最初编写的Python代码是对齐标准实现的,所以会和维基示例匹配。

内容的提问来源于stack exchange,提问作者Khi-Lee Klock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 03:36:02