在 PHP 中實現整數溢出

在用 PHP 翻譯別人用 Java 寫的以下一段代碼時,碰到了一些關於 PHP 整數操做的問題。php

Java 代碼:java

public static long hash(String string) {
        long h = 1125899906842597L;
        int len = string.length();
        for (int i = 0; i < len; i++) {
            h = 31*h + string.charAt(i);
        }
        return h;
    }

因爲 Long 類型的 h 的初始值就比較大,通過屢次乘以 31 以後會溢出。可是移除後 h 的值也不會爲 0,運算能夠正常繼續。可是在 PHP(5.3.27_1) 中,當整數溢出後,用 intval 取值會獲得 0。而 PHP 中用來作大數運算的 BC_MATH 中的函數雖然能夠進行大數運算,可是沒法在溢出後截斷溢出。這讓人很鬱悶。又不想光爲這個簡單的功能去用 C 寫一個擴展。最後又複習了一邊《深刻理解計算機系統》中第二章關於整數運算的描述,寫了一個整數溢出的函數。函數

function overflow_long($value)
    {
        $max_int = bcsub(bcpow(2, 63), 1);
        $int_span = bcpow(2, 64);
        $min_int = bcsub(bcadd($max_int, 1), $int_span);
        $mod_value = bcmod($value, $int_span);
        if (bccomp($mod_value, $max_int) > 0) {
            return bcsub($mod_value, $int_span);
        } elseif (bccomp($mod_value, $min_int) < 0) {
            return bcadd($mod_value, $int_span);
        } else {
            return $mod_value;
        }
    }

而後實現上述 Java 代碼的功能。this

private function hash($str) {
        $char_arr = str_split($str);
        $len = strlen($str);
        $h = 1125899906842597;
        for($i=0; $i<$len; $i++) {
            echo $h, "<br />";
            $h = $this->overflow_long(bcmul(31, $h)) + ord($char_arr[$i]);
        }   
        return $h; 
    }
相關文章
相關標籤/搜索