最简单的方法是将符号位归零,然后将零映射到其他值:
Long y = x & Long.MAX_VALUE;
return (y == 0)? 42: y;
这很简单,只使用一个 if/ternary 运算符,平均碰撞率约为 50%。有一个缺点:它将 4 个不同的值(0、42、MIN_VALUE、MIN_VALUE+42)映射到一个值(42)。所以对于这个值,我们有 75% 的碰撞,而对于其他值 - 正好是 50%。
更均匀地分布冲突可能更可取:
return (x == 0)? 42: (x == Long.MIN_VALUE) ? 142: x & Long.MAX_VALUE;
此代码为 2 个值提供 67% 的冲突,为其他值提供 50% 的冲突。您不能更均匀地分布碰撞,但可以选择这 2 个最碰撞的值。缺点是这段代码使用了两个 if/三元运算符。
仅使用一个 if/三元运算符时,可以避免 75% 的单个值冲突:
Long y = x & Long.MAX_VALUE;
return (y == 0)? 42 - (x >> 7): y;
此代码为 2 个值提供 67% 的冲突,为其他值提供 50% 的冲突。选择这些最冲突的值的自由度较低:0 映射到 42(您几乎可以选择任何值);MIN_VALUE 映射到42 - (MIN_VALUE >> 7)
(您可以将 MIN_VALUE 移动 1 到 63 之间的任何值,只需确保A - (MIN_VALUE >> B)
不会溢出)。
没有条件运算符(但代码更复杂)也可以获得相同的结果(2 个值的冲突为 67%,其他值的冲突为 50%):
Long y = x - 1 - ((x >> 63) << 1);
Long z = y + 1 + (y >> 63);
return z & Long.MAX_VALUE;
这为值“1”和“MAX_VALUE”提供了 67% 的冲突。如果更方便地获取其他一些值的大多数冲突,只需将此算法应用于x + A
,其中 'A' 是任意数字。
此解决方案的改进变体:
Long y = x + 1 + ((x >> 63) << 1);
Long z = y - (y >> 63);
return z & Long.MAX_VALUE;