64位浮点文字PHP

kry*_*ryo 8 php literals double-precision pack long-integer

我试图在PHP中将64位浮点数转换为64位整数(并返回).我需要保留字节,所以我正在使用pack和unpack函数.我正在寻找的功能基本上是Java的Double.doubleToLongBits()方法.http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#doubleToLongBits(double)

我设法得到这个远远的帮助来自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];
}
Run Code Online (Sandbox Code Playgroud)

这很好用,大部分......

echo decode(encode(10000000000000));
Run Code Online (Sandbox Code Playgroud)

亿

echo encode(10000000000000);
Run Code Online (Sandbox Code Playgroud)

1.1710299640683E-305

但是这里变得棘手......

echo decode(1.1710299640683E-305);
Run Code Online (Sandbox Code Playgroud)

-6629571225977708544

我不知道这里有什么问题.亲自试试:http://pastebin.com/zWKC97Z7

你需要在Linux上使用64位PHP.该网站似乎模拟了该设置:http://www.compileonline.com/execute_php_online.php

Jac*_*ski 2

它工作正常,这种情况下唯一的问题是逻辑:

echo decode(1.1710299640683E-305);
Run Code Online (Sandbox Code Playgroud)

您不能使用echo函数的“舍入”和“人类可读”输出来解码原始值(因为您将失去此双精度值的精度)。

如果您将encode(10000000000000)的返回值保存到变量中,然后尝试再次解码它,它将正常工作(您可以在10000000000000上使用echo而不会丢失精度)。

请参阅下面的示例,您也可以在PHP 编译器上执行:

<?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!
?>
Run Code Online (Sandbox Code Playgroud)