The C code of MurmurHash3包含以下部分:
uint64_t k1 = 0;
uint64_t k2 = 0;
switch(len & 15)
{
case 15: k2 ^= ((uint64_t)tail[14]) << 48;
case 14: k2 ^= ((uint64_t)tail[13]) << 40;
case 13: k2 ^= ((uint64_t)tail[12]) << 32;
case 12: k2 ^= ((uint64_t)tail[11]) << 24;
case 11: k2 ^= ((uint64_t)tail[10]) << 16;
case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
(tail
的类型为uint8_t *
)
据我所知,它与OR操作没有什么不同。在这里使用XOR有什么区别?是优化吗?如果是,那是什么?还是我遗漏了这两个操作员的行为差异?
我已经知道XOR和OR之间的区别。但是在这种情况下,由于该值在开始时被清零并且异或的值不重叠,所以该行为与OR不应有任何不同。因此,我想问一问为什么作者选择它而不是OR(它比XOR imho更好地传达了意图)。
答案 0 :(得分:1)
是的,在这种情况下,它们是完全等效的。此外,由于它们是等效的,因此编译器可以单独使用它进行优化。编译时,您无法保证它实际上是xor xor。实际上,从更一般的层面上讲,只要编译器生成的代码的可观察行为相同,就不能保证它会是它们中的任何一个。
使用xor的合理原因是,这是有问题的程序员首先想到的东西,或者代码最初是用很重要的方式编写的,但是后来又变成了不需要的版本物。但是由于在这种情况下它们是等效的,所以很难知道。
答案 1 :(得分:0)
为什么在OR上使用XOR?
如果人们可以在此限制性代码中使用|
或^
来获取和存档相同的功能,则首选的应该反映更大的问题。
^
保留熵@Nominal Animal。
当代码试图形成哈希时(如MurmurHash3),^
比|
更好。 ^
翻转位通常会导致1和0的合理分布。 |
偏向1。
许多散列算法会像binary addition with no carries一样“添加” a
和b
,也就是说a ^ b
而不是a | b
。因此,在这种哈希算法环境中,^
传达了更好的算法意图。
有时我会遇到确实使用|
的哈希代码,但不幸的是,结果会产生偏差,而^
可以正常工作。 IMO,哈希码中的|
是一个可能会产生偏见的危险信号。