【问题标题】:Hash/digest with determined (small) amount of variants具有确定(少量)变体的哈希/摘要
【发布时间】:2016-07-19 13:44:11
【问题描述】:

我只需要从字符串中获取 16 个(或其他少量)可能的哈希值,用于根据联系人姓名对联系人进行颜色编码。

我曾尝试获取 crc32 哈希,然后获取第一个符号,即十六进制数字:

$contact = 'Robin Hood';
$colors = [
     '0' => 'F8BBD0',
     '1' => 'E1BEE7',
     ...
     'e' => 'D7CCC8',
     'f' => 'CFD8DC',
];
$firstLetter = hash('crc32', $contact)[0];
return '#' . $colors[$firstLetter];

但是,我对这种方法的良好分布表示怀疑。如何从字符串中获取少量且确定数量的变体摘要?

【问题讨论】:

    标签: javascript php hash colors


    【解决方案1】:

    如果您主要关心的是良好的分布,我会使用一个好的伪随机引擎:

    $colorKey = bin2hex(openssl_random_pseudo_bytes(1))[0];
    return '#' . $colors[$colorKey];
    

    我不能说这与散列的第一个字符的分布相比如何,但这绝对适合您的目的。


    编辑:由于您需要哈希,我针对 500 个随机名称的文本文件测试了各种哈希,发现 crc32 具有最均匀的分布。我不知道您期望有多少个名称或您需要的发行版有多好,但您的解决方案对我来说似乎是一个不错的选择:

    <?php
    function sd_square($x, $mean) { return pow($x - $mean,2); }
    
    function sd($array) {
        return sqrt(array_sum(array_map("sd_square", $array, array_fill(0,count($array), (array_sum($array) / count($array)) ) ) ) / (count($array)-1) );
    }
    
    $crcColorCounts = array_fill_keys(range(0, 15), 0);
    $file = fopen('random_names.txt', 'r');
    while ($contact = fgets($file)) {
        $hash = hash('crc32', $contact);
        $letter = $hash[0];
        $crcColorCounts[hexdec($letter)]++;
    }
    fclose($file);
    print_r($crcColorCounts);
    echo 'Standard deviation: ', sd($crcColorCounts);
    

    输出:

    Array
    (
        [0] => 32
        [1] => 26
        [2] => 33
        [3] => 31
        [4] => 40
        [5] => 29
        [6] => 33
        [7] => 20
        [8] => 33
        [9] => 30
        [10] => 39
        [11] => 27
        [12] => 36
        [13] => 33
        [14] => 29
        [15] => 30
    )
    Standard deviation: 4.8815127436755
    

    (取自this answer的标准差函数。)

    我还尝试了 MD5、SHA1 和 CRC32 的最后一个字符。所有返回的标准差都在 7 左右,使 CRC32 的第一个字符成为赢家。

    【讨论】:

    • 不,我的任务不是随机的,而是每次根据这个人的名字为同一个人提供相同的(永久)哈希。
    • @vatavale 请查看我的编辑。我测试了哈希的分布。
    • 哇!这是一个令人印象深刻的答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 2014-07-24
    • 2017-11-15
    相关资源
    最近更新 更多