如果我在PHP中散列了一堆随机数,并将散列转换为基-10,那么数字9永远不会出现在结果整数的末尾。我想我一定是在MD5哈希的工作方式或PHP处理方式中遗漏了一些显而易见的东西。
我注意到这一点,因为我有一个(所有不同的)字符串的列表,并且需要将它们随机地分成两组( 90%的字符串在桶A中,10%在桶B中)。我想我只需要散列字符串,转换为基-10,然后执行如下操作:
如果(( md5_hash_in_base_ten % 100 )< 90 )使用桶A
否则用桶B
但是事实证明,9位数从来没有出现在结果整数的末尾,所以从来没有选择桶B。
我知道有上百万种随机分组字符串的方法,但我对这个问题的不同解决方案并不感兴趣。我只是对我的测试代码的(可能的)奇怪结果感到好奇。
for( $i = 0; $i < 10000; $i++ ) {
$r = rand();
$bc = base_convert( md5( $r ), 16, 10 );
echo $bc . '<br>';
}
其中一组结果如下:
302600829905161600608260662606624826442 59585669553455458666446844468880068068 330999075520965568846868468088242088640 192131673950084244086840262480428482262 219128507900677482440460800240644480082 255318670176792246888206600668682602264 240208061481025440684246208684488420642 294217394926758646048046684044640488204 278449747058183168002848628868886688226 195713211929924564840668644204640202264 249037264096573760228220842660668480862 207646493898559360028468248404088664884 169051134173421386202080006468046600882 91273057168422960202446286266888840680 289959365012917366428044866648660802042 172462762250895562808826226442626868482 21264346015514864044284484068442686886 37414331404805136842220266424646680664 76064003552382186484240646428006806660 316804269790551588866666266482482808288 142781990240421424242486286048486626288 12211092583070068208404402226428806286 164064659807615146666228064640060626026 336702095492281784288600868224440806802 264447819530445920480408448628866828002 127283138187204864060642440804622660688 220658311731241408862084402042406680248 71873545317929552826606228242842664868
如果我们用数字9表示,它看起来是这样的:
想法?
发布于 2019-08-30 18:05:06
PHP的base_convert
函数是,而不是为任意大的数字而设的,正如函数文档页上的红色框所指出的。
您可以通过以下方式验证您自己:
echo ('a' == base_convert(base_convert('a', 16, 10), 10, 16)) ? 1 : 0;
echo ('abcdefabcdefabcdef' == base_convert(base_convert('abcdefabcdefabcdef', 16, 10), 10, 16)) ? 1 : 0;
这将打印1
和0
:将数字a
(十六进制)转换为十进制,并返回按预期工作,但数字abcdefabcdefabcdef
(十六进制)会导致base_convert
不精确。
要解决这个问题,您需要使用一个能够处理任意长度的数字的函数。例如,查看文档页面上的其中一条评论 (函数convBase
)。
发布于 2019-08-30 18:05:26
您使用的数字比base_convert所能处理的要大。请参阅PHPDocuments这里。
MD5哈希数为128位,这比大多数库需要处理的要多。您的转换结果无法保持精度。在您的例子中,您可以使用GNU多重精度库。
<?php
/*use gmp library to convert base. gmp will convert numbers > 32bit*/
function gmp_convert($num, $base_a, $base_b)
{
return gmp_strval ( gmp_init($num, $base_a), $base_b );
}
for( $i = 0; $i < 5; $i++ ) {
$r = rand();
$h = md5($r);
$bc = base_convert( $h, 16, 10 );
$gmp = gmp_convert( $h, 16, 10 );
echo "Random value: " . $r . PHP_EOL;
echo "MD5 Hash: " . $h . PHP_EOL;
echo "Base converted: " . $bc . PHP_EOL;
echo "GMP converted: " . $gmp . PHP_EOL;
}
?>
它将输出:
$ php -f foo.php
Random value: 1198279904
MD5 Hash: 714ae450dedfd56314b47f84e1922c9a
Base converted: 150591624287845962826662264228684068862
GMP converted: 150591624287845974934538261676650802330
Random value: 2000471768
MD5 Hash: 6359b22761538dd02822732ba45c66bf
Base converted: 132059299392045104262828066404880468000
GMP converted: 132059299392045115619248080281367504575
Random value: 851022648
MD5 Hash: 1e95df1b73599a92637982bab7814fc4
Base converted: 40655017257670256242606204044284220868
GMP converted: 40655017257670268183638196631434776516
Random value: 711523039
MD5 Hash: e23aff29be3bb611abbb3736fbdd4d07
Base converted: 300711855586863926204240426446264628688
GMP converted: 300711855586863939825593015112763788551
Random value: 953421999
MD5 Hash: a5990cd2bbab7707db05ebd3b468df17
Base converted: 220117300808777322406606064084840664268
GMP converted: 220117300808777304730115892103715806999
https://stackoverflow.com/questions/57731139
复制相似问题