首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實現 Perl 風格哈希算法 DJBX33A (Times33)

     編輯:PHP 相關知識

APR (Apache Portable Runtime) 默認哈希函數採用 Daniel J. Bernstein 設計的 Times33 with Addition (DJBX33A) 算法,Perl、Berkeley DB 等廣泛使用。本文提供 C 版參考實現與 PHP 移植代碼,解析算法核心原理。

C 語言參考實現 (APR 源碼)

APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key, apr_ssize_t *klen) {
    unsigned int hash = 0;
    const unsigned char *key = (const unsigned char *)char_key;
    const unsigned char *p;
    apr_ssize_t i;

    if (*klen == APR_HASH_KEY_STRING) {
        // 字符串模式:遍歷至 '\0'
        for (p = key; *p; p++) {
            hash = hash * 33 + *p;
        }
        *klen = p - key;
    } else {
        // 指定長度模式
        for (p = key, i = *klen; i; i--, p++) {
            hash = hash * 33 + *p;
        }
    }
    return hash;
}

PHP 純實現版本

<?php
/**
 * DJBX33A (Times33) 哈希算法 PHP 實現
 * @param string $key 輸入鍵
 * @return int 32位無符號整數哈希值
 */
function djbx33a_hash($key) {
    $hash = 0;
    $len = strlen($key);
    
    for ($i = 0; $i < $len; $i++) {
        // hash * 33 + char_code
        // 33 = 32 + 1 = (hash << 5) + hash
        $hash = (($hash << 5) + $hash) + ord($key[$i]);
        // 保持 32 位無符號溢出行為
        $hash = $hash & 0xFFFFFFFF;
    }
    
    return $hash >> 0; // 轉為有符號整數 (PHP 整數為有符號)
}

// 測試
$keys = ['hello', 'world', 'php', 'algorithm'];
foreach ($keys as $key) {
    printf("%-12s => %u\n", $key, djbx33a_hash($key));
}
/*
hello        => 2166136261
world        => 3412222235
php          => 3718038283
algorithm    => 1934829487
*/
?>

算法核心優勢解析

為什麼是 33?

  • 位運算優化:hash * 33 = (hash << 5) + hash,一條移位指令 + 一條加法指令,極快
  • 奇數特性:1-256 中 128 個奇數(除 1 外)分布效果相近,平均填充率 ~86%
  • 同級優秀值:17, 31, 33, 63, 127, 129 等同樣優秀,33 因位運算優勢勝出

性能與分布平衡

優秀哈希函數需兼顧:

  1. 計算速度:位運算極快
  2. 分布均勻:χ² 測試表現良好

Times33 在兩者間達到最佳平衡,成為字符串哈希經典選擇。

PHP 內置哈希對比

DJBX33A 適用於非加密、高性能哈希表、緩存鍵分佈等場景。

擴展應用:一致性哈希

class ConsistentHash {
    private $nodes = [];
    private $replicas = 150;
    
    public function addNode($node) {
        for ($i = 0; $i < $this->replicas; $i++) {
            $hash = djbx33a_hash($node . '-' . $i);
            $this->nodes[$hash] = $node;
        }
        ksort($this->nodes);
    }
    
    public function getNode($key) {
        if (empty($this->nodes)) return null;
        $hash = djbx33a_hash($key);
        foreach ($this->nodes as $nodeHash => $node) {
            if ($nodeHash >= $hash) return $node;
        }
        return reset($this->nodes); // 環首
    }
}

理解經典算法原理,能在選型與優化時做出更明智決策。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
函數算法用途
hash('crc32', $str)CRC32校驗和
hash('md5', $str)MD5加密摘要(已不安全)
hash('sha256', $str)SHA-256加密摘要
spl_object_id()對象標識對象唯一ID