doumisha5081 2014-06-01 17:33
浏览 102
已采纳

64位浮点文字PHP

I'm trying to convert a 64-bit float to a 64-bit integer (and back) in php. I need to preserve the bytes, so I'm using the pack and unpack functions. The functionality I'm looking for is basically Java's Double.doubleToLongBits() method. http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#doubleToLongBits(double)

I managed to get this far with some help from the comments on the php docs for pack():

function encode($int) {
        $int = round($int);

        $left = 0xffffffff00000000;
        $right = 0x00000000ffffffff;

        $l = ($int & $left) >>32;
        $r = $int & $right;

        return unpack('d', pack('NN', $l, $r))[1];
}
function decode($float) {
        $set = unpack('N2', pack('d', $float));
        return $set[1] << 32 | $set[2];
}

And this works well, for the most part...

echo decode(encode(10000000000000));

100000000

echo encode(10000000000000);

1.1710299640683E-305

But here's where it gets tricky...

echo decode(1.1710299640683E-305);

-6629571225977708544

I have no idea what's wrong here. Try it for yourself: http://pastebin.com/zWKC97Z7

You'll need 64-bit PHP on linux. This site seems to emulate that setup: http://www.compileonline.com/execute_php_online.php

  • 写回答

3条回答 默认 最新

  • dtj2ww9500 2014-06-03 19:58
    关注

    It is working properly, the only problem in this case is in logic of:

    echo decode(1.1710299640683E-305);
    

    You can't use "rounded" and "human readable" output of echo function to decode the original value (because you are loosing precision of this double then).

    If you will save the return of encode(10000000000000) to the variable and then try to decode it again it will works properly (you can use echo on 10000000000000 without loosing precision).

    Please see the example below which you can execute on http://www.compileonline.com/execute_php_online.php as well:

    <?php
        function encode($int) {
            $int = round($int);
    
            $left = 0xffffffff00000000;
            $right = 0x00000000ffffffff;
    
            $l = ($int & $left) >>32;
            $r = $int & $right;
    
            return unpack('d', pack('NN', $l, $r))[1];
        }
    
        function decode($float) {
            $set = unpack('N2', pack('d', $float));
            return $set[1] << 32 | $set[2];
        }
    
        echo decode(encode(10000000000000)); // untouched
        echo '<br /><br />';
    
        $encoded = encode(10000000000000);
        echo $encoded; // LOOSING PRECISION! 
        echo ' - "human readable" version of encoded int<br /><br />';
    
        echo decode($encoded); // STILL WORKS - HAPPY DAYS!
    ?>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料