计算字符串的自定义长度、自定义进制随机均匀短散列值

要生成自定义长度、自定义进制的随机均匀短散列值,可以结合哈希函数和进制转换来实现。哈希函数可以将字符串映射为固定长度的二进制值,然后根据自定义的进制进行编码,生成你需要的短散列值。我们可以使用 PHP 来实现该功能,以下是具体的步骤:

实现步骤

  1. 输入字符串的哈希值:使用常见的哈希算法如 MD5 或 SHA-256 生成散列值。
  2. 转换哈希值为数字:将生成的哈希值转换为数字表示。
  3. 根据自定义进制转换:将数字转换为你想要的进制(例如 62 进制,包含数字、大小写字母)。
  4. 控制散列长度:生成的散列值可以根据需求来截断或补齐为特定长度。

代码实现

下面是使用 PHP 实现该逻辑的代码示例:

php 复制代码
/**
 * 生成自定义长度的自定义进制随机均匀短散列值
 *
 * @param string $inputStr   需要计算的字符串
 * @param int    $len        指定散列值字符长度(可取1~32位),默认32位(2:显示0~1;4:显示0~3;8:显示0~7;10:显示0~9;16:显示0~F;32:显示0~V;64:显示0~/)...")
 * @param int    $base       自定义的进制,默认16进制
 * @return string
 */
public static function generateCustomShortHash($inputStr, $len=32, $base=16, $prefix='', $suffix='',$times=0){
        $md5 = strtoupper(md5($prefix.$inputStr.$suffix));
        $base_str = array (
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 
            'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 
            'X', 'Y' );//去除了I、L、O、Z四字母,(I、i、L、l与数字1相似,O、o与数字0相似,Z、z与数字2相似,1~F属于16进制常规范筹不宜删减);
        $b_one = ceil(log($base,2));//每一位字符需要2进制字符长度
        $h_one = ceil($b_one/4);//每一位字符需要16进制字符长度
        $m_len = $b_one % 4;//非4的整数倍时高位丢弃,计算丢弃的位数
        if(ceil(($b_one * $len) / 4) > strlen($md5)){//需要总16进制字符长度超过最大字符长度
            return false;
        }
        for ($run_num=0; $run_num < 100; $run_num++) { 
            $hex = isset($hex)?strtoupper(md5($hex)):$md5;
            $strabbr = '';
            for ($i = 0; $i < $len; $i++) {//循环每一位目标字符生成工作
                $subHex = substr($hex, $i*$h_one, $h_one);//按目标字符所需16进制字符长度进行截取
                $b1_str = ($h_one - 1) * 4 + ($m_len?:4);//生成二进制位运算的1字符数
                $b0_str = $m_len?(4-$m_len):0;//生成二进制位运算的0字符数
                $b_str = $m_len?str_repeat('0',$b0_str).str_repeat('1',$b1_str):str_repeat('1',$b1_str);//拼接二进制位运算的字符串
                $int = (bindec('0b'.$b_str)) & (hexdec('0x'.$subHex));//按位与保留有效位值
                $strabbr .= $base_str[$int];//从数组中获取对应字符
            }
            //存表逻辑
            if(Urlabbr::selectcount(['strabbr'=>$strabbr])==0){
                $urlabbr_data = [
                    'str'=>$inputStrc,
                    'strmd5'=>md5($inputStr),
                    'strabbr'=>$strabbr,
                    'run_num'=>$run_num+1,
                    'views'=>0,
                    'createtime'=>$times?:time(),
                    'updatetime'=>$times?:time(),
                    'switch'=>1,
                ];
                Urlabbr::addid($urlabbr_data);
                break;
            }
        }
        if($run_num >= 100){ //撞库次数超过100
            return false;
        }
        //返回数据
        return $strabbr;
    }

代码说明

  1. 字符表定义 :我们使用 0123456789ABCDEFGHJKMNPQRSTUVWXY 作为 32 进制字符表,去除了I、L、O、Z四字母,(I、i、L、l与数字1相似,O、o与数字0相似,Z、z与数字2相似,1~F属于16进制常规范筹不宜删减);

  2. 哈希计算 :我们使用 hash('sha256', $inputStr) 来计算输入字符串的 SHA-256 哈希值。由于 SHA-256 生成 64 位的十六进制数(256 位),我们可以选取前 15 位哈希值转成十进制,以确保数值足够大且不会溢出。

  3. 进制转换 :将哈希值的十进制数字逐位转为 32 进制,通过 num % $base 计算余数,从而获得 32 进制字符,并将字符拼接到结果中。

  4. 结果处理 :使用 str_pad() 来确保最终生成的短散列值具有指定的长度,不足的部分以 0 补齐。

运行结果

对于输入字符串 "example_string",生成了一个 8 位长度的 32 进制短散列值。

扩展

  • 更大进制:如果需要更高的进制,可以扩展字符集。例如支持 95 个可打印字符(ASCII)。
  • 随机性增强:可以在哈希值基础上添加时间戳、随机数等增强散列的随机性。
  • 更长哈希:使用不同的哈希算法或截取更多位数,可以增加散列的多样性。
相关推荐
九圣残炎17 分钟前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu22 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
丫头,冲鸭!!!42 分钟前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
Re.不晚1 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
为什么这亚子2 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
2 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
~yY…s<#>2 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
幸运超级加倍~3 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
yannan201903133 小时前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法3 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法