4
   pack('H*', dechex(12345678900)) /* on 32bit */  
!= pack('H*', dechex(12345678900)) /* on 64bit */

なぜ ?

4

1 に答える 1

1

修正方法はわかりませんが、なぜこれが起こっているのかはわかっていると思います。ここにバグはありません - マニュアルhttp://php.net/manual/en/function.dechex.phpからまっすぐに

変換できる最大数は 10 進数で 4294967295 であり、結果は "ffffffff" になります。

PHP の「内部」で何が起こっているのか正確にはわかりませんが、おそらく 32 ビット符号なし整数のオーバーフロー (12,345,678,900 > 4,294,967,295) を引き起こしている可能性があります。64 ビットでは、この制限は 18,446,744,073,709,551,615 である必要があるため、dechex は「正しい」値を返します (32 ビットと 64 ビットの違いは文書化されていないようで、テスト用の 64 ビット システムがないため、間違っている可能性があります)。

//編集:

最後の手段として、GMP拡張機能を使用して 32 ビット システム用の独自の 16 進関数を作成することもできますが、それでは大量のオーバーヘッドが発生します。おそらく、現代のプログラミングで知られている最も遅い実装の 1 つになるでしょう。

//Edit2:

BCMathを使用して関数を作成しました。現在、私は Windows を使用しており、GMP の正しい dll を見つけるのに苦労していました。

function dechex32($i) {
    //Cast string
    $i = (string)$i;
    //Initialize result string
    $r = NULL;
    //Map hex values 0-9, a-f to array keys
    $hex = array_merge(range(0, 9), range('a', 'f'));
        //While input is lagrer than 0
        while(bccomp($i, '0') > 0) {
            //Modulo 16 and append hex char to result
            $r.= $hex[$mod = bcmod($i, '16')];
            //i = (i - mod) / 16
            $i = bcdiv(bcsub($i, $mod), '16');
        }
    //Reverse result and return
    return strrev($r);
}

var_dump(dechex32(12345678900));
/*string(9) "2dfdc1c34"*/

徹底的にテストしませんでしたが、うまくいくようです。最後の手段として使用 - 100,000 回の反復による大まかなベンチマークでは、ネイティブ実装よりも最大 40 倍遅いことが示されました。

于 2011-05-09T23:14:52.773 に答える