我编写了一个快速画布可视化,以查看我从C ++移植到JavaScript的散列算法的分布。
我看到奇怪的行为,无论我调整散列值是什么,0都是严重偏置的,因为它的选择频率是散列函数中大多数其他数字的两倍。
您可以在http://jsfiddle.net/x5L73/2/
看到该演示和原始C ++算法:http://www.azillionmonkeys.com/qed/hash.html
我所指的代码部分,位于jsFiddle的底部:
// hash is 0 twice as often as anything else
var hash = app.Hash( word ) % ( 3499 )
, b1 = 0|hash / 59
, b2 = hash % 59;
对我来说奇怪的是,hash
为零,是任何其他值的两倍,无论我选择通过什么来修改它。在此示例中,它为1/3499
次,而任何其他数字均为1/6998
次。这是通过蛮力测试确定的:
if( hash!==1234 ){ nonZero++; }else{ zero++ } // 1234 is a random number to check
if( Math.random() < .00001 ){ console.log( zero, nonZero, 0|nonZero/zero ); }
我在这里缺少什么?
答案 0 :(得分:4)
尽管这是一个非常有趣的事实,在处理整数时可能会派上用场,就像哈希一样,错误是不,因为JavaScript 有 a负零也是......
OP报告的原因是:
这是因为我不小心丢弃了可视化中的所有负数。
是的,负数并不是那么微不足道,我们的思想往往会忽略它们 - 尤其是当它们专注于一个长时间涉及整数的特定的困难问题时,就像试图找出好的哈希方法一样,然后切换看似简单的任务:显示结果......
所以真正的答案是:除了负零之外,JavaScript还有更多的负数......不要忘记将它们计算在内 - 即使在 easy < / em>可视化任务。
TL; DR
我将此留在此处,因为可能会为将来遇到类似问题的任何人派上用场,因为可能会导致类似的情况。
看看这个问题:+0 and -0 in JavaScript (negative zero and positive zero in JavaScript)
引用:
JavaScript使用IEEE 745 standard来表示数字。来自Wikipedia:
带有关联符号的有符号零为零。在普通算术中,-0 = + 0 = 0.但是,在计算中,某些数字表示允许存在两个零,通常用 -0(负零)和 +0表示(正零)。这发生在整数的一些有符号数表示中,并且在大多数浮点数表示中。数字0通常编码为+0,但可以用+0或-0表示。
用于浮点运算的IEEE 754标准(目前大多数支持浮点数的计算机和编程语言都使用)需要+0和-0。零可以被认为是扩展实数线的变体,使得1 / -0 =-∞和1 / + 0 = +∞,除以0仅对于±0 /±0和±∞/±∞未定义