为何这段PHP代码误报JOAAT哈希值存在数组重复?
问题描述
我编写了如下PHP代码:
$num = 0; $arr = array(); for ($i = 1; $i <= 10000; $i++) { $hashed = hash("joaat", "TEST" . $num + $i); if (!in_array($hashed, $arr)) { array_push($arr, $hashed); } else { // array_push($arr, $hashed); echo "Duplicate " . $hashed . "\n"; echo "<br>"; echo "TEST" . $num + $i; echo "<br>"; break; } } echo "ARRAY---------------------------------------------------------------------------------------------------------------------------------"; echo "<br>"; print_r($arr);
代码逻辑为:循环生成"TEST1"至"TEST10000"的字符串,使用JOAAT哈希算法计算哈希值,检查该哈希值是否存在于数组$arr中。若不存在则将其加入数组,若存在则输出重复信息并终止循环。
实际运行时,程序触发了else分支,输出重复哈希值及原字符串并终止,但我查看数组后却未找到该重复哈希值。请问这是什么原因?是否我的代码存在缺陷?
问题根源:运算符优先级错误
你的代码存在明确缺陷,核心问题是PHP运算符优先级导致字符串拼接逻辑完全偏离预期:
在PHP中,算术运算符(+)的优先级高于字符串连接运算符(.),所以代码中的"TEST" . $num + $i会被PHP解析为:
("TEST" . $num) + $i
而非你预期的"TEST" . ($num + $i)。
具体执行过程:
$num的值为0,"TEST" . $num会生成字符串"TEST0"。- 字符串与数字执行加法时,PHP会强制将字符串转换为数字:
"TEST0"无法被解析为有效数字,会被转为0。 - 最终
"TEST0" + $i的结果是0 + $i = $i(整数类型)。 - 调用
hash("joaat", $i)时,PHP会把整数$i转为字符串(如"1"、"2")来计算哈希。
为什么会出现“重复却找不到哈希”的矛盾?
当循环到某个$i时,hash("joaat", (string)$i)的结果恰好和之前某个$j的哈希碰撞,程序进入else分支。但你在输出原字符串时同样犯了运算符优先级错误:echo "TEST" . $num + $i输出的不是"TESTX",而是$i的数值(同样的优先级逻辑,"TEST0"转0加$i等于$i),这就导致你误以为重复的是某个"TESTX"的哈希,但实际上数组里存的是数字字符串的哈希,你看到的输出数字对应的哈希确实在数组中,只是被错误的输出误导了。
修复方案
给$num + $i加上括号,强制改变运算顺序,确保先计算数值再拼接字符串:
// 修正哈希计算的字符串拼接逻辑 $hashed = hash("joaat", "TEST" . ($num + $i)); // 同时修正输出语句的运算符优先级问题 echo "TEST" . ($num + $i);
修改后代码就能按照预期生成"TEST1"到"TEST10000"的字符串并计算哈希,不会再出现逻辑错误。
内容的提问来源于stack exchange,提问作者Jugs
相关产品推荐
相关产品推荐

