Javascript和Python中XOR操作的结果不一致

Javascript和Python中XOR操作的结果不一致,javascript,python,math,operators,xor,Javascript,Python,Math,Operators,Xor,我正在将一个又长又难看的函数从JS移植到Python,它基本上是在给定一些输入参数的情况下计算某种哈希字符串。在移植和修改代码之后,做了一些测试,(令人惊讶的是),我没有得到同样的结果 我做了一些调试,到达了一条开始把一切都搞糟的线路,结果是一个异或操作。因此,长话短说,我已经孤立了一个简单的例子,展示了如何使用相同的值,得到不同的结果 这是JS代码: hex_str = "0xA867DF55" crc = -1349196347 new_crc = (crc >> 8) ^ he

我正在将一个又长又难看的函数从JS移植到Python,它基本上是在给定一些输入参数的情况下计算某种哈希字符串。在移植和修改代码之后,做了一些测试,(令人惊讶的是),我没有得到同样的结果

我做了一些调试,到达了一条开始把一切都搞糟的线路,结果是一个异或操作。因此,长话短说,我已经孤立了一个简单的例子,展示了如何使用相同的值,得到不同的结果

这是JS代码:

hex_str = "0xA867DF55"
crc = -1349196347
new_crc = (crc >> 8) ^ hex_str
//new_crc == 1472744368
这与Python中的代码相同:

hex_str = "0xA867DF55"
crc = -1349196347
new_crc = (crc >> 8) ^ int(hex_str, 16)
//new_crc == -2822222928
唯一的区别是hex_str在Python中显式转换为整数


在实际代码中,此计算在for循环中运行。hex_str和crc在每次迭代中都会更新。在最初的几次迭代中,python中的一切都很好,但是当hex_str和crc得到上面显示的值时,一切都开始混乱起来。

区别在于如何处理有符号数字。Python将整数视为在所有上下文中具有任意位长度。对于位操作,负数被视为有“足够”的前导位用于任何目的,因此负数与正数的异或将始终导致负数。另一方面,在JavaScript中,位运算中的整数被视为有符号的32位数字,因此结果可能不同

CRC32使用32位整数计算。要模拟Python中的行为,可以通过获取任何结果的较低32位,将所有操作限制为32位:

>>> -2822222928 & (2 ** 32 - 1)
1472744368
或应用于您的代码

hex_str = "0xA867DF55"
crc = -1349196347
new_crc = ((crc >> 8) ^ int(hex_str, 16)) & (2 ** 32 - 1)

区别在于如何处理有符号的数字。Python将整数视为在所有上下文中具有任意位长度。对于位操作,负数被视为有“足够”的前导位用于任何目的,因此负数与正数的异或将始终导致负数。另一方面,在JavaScript中,位运算中的整数被视为有符号的32位数字,因此结果可能不同

CRC32使用32位整数计算。要模拟Python中的行为,可以通过获取任何结果的较低32位,将所有操作限制为32位:

>>> -2822222928 & (2 ** 32 - 1)
1472744368
或应用于您的代码

hex_str = "0xA867DF55"
crc = -1349196347
new_crc = ((crc >> 8) ^ int(hex_str, 16)) & (2 ** 32 - 1)

好吧,我试过你的解决方案,虽然一开始它对我原来问题的值有效,但通过其他组合,我仍然得到了奇怪的结果。最后我使用了ctypes.c_int函数,它给了我更可靠的结果。我不知道为什么你应用32位掩码的解决方案并不总是有效,但无论如何,谢谢你给我一些提示@KilianPerdomo您可能仍然会得到错误的结果符号,因此如果结果大于
2**31-1
,则必须调整符号。使用
ctypes.c_int
可能是更简单的解决方案,尽管我不确定它是否保证有32位。为了安全起见,你可以使用
ctypes.c_int32
。我尝试了你的解决方案,尽管一开始它对我原来问题的值有效,但使用其他组合,我仍然得到了奇怪的结果。最后我使用了ctypes.c_int函数,它给了我更可靠的结果。我不知道为什么你应用32位掩码的解决方案并不总是有效,但无论如何,谢谢你给我一些提示@KilianPerdomo您可能仍然会得到错误的结果符号,因此如果结果大于
2**31-1
,则必须调整符号。使用
ctypes.c_int
可能是更简单的解决方案,尽管我不确定它是否保证有32位。为了安全起见,您可以使用
ctypes.c_int32