64位浮点文字PHP

时间:2014-06-01 17:33:11

标签: php long-integer literals pack double-precision

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

我设法通过对pc()的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));
  

亿

echo encode(10000000000000);
  

1.1710299640683E-305

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

echo decode(1.1710299640683E-305);
  

-6629571225977708544

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

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

3 个答案:

答案 0 :(得分:4)

$x = encode(10000000000000);
var_dump($x); //float(1.1710299640683E-305)
echo decode($x); //10000000000000

$y = (float) "1.1710299640683E-305";
var_dump($y); //float(1.1710299640683E-305)
echo decode($y); //-6629571225977708544 

$z = ($x == $y);
var_dump($z); //false

http://www.php.net/manual/en/language.types.float.php

  

......永不信任   浮点数结果为最后一位数,并且不比较浮点数   点数直接表示相等。如果需要更高的精度,   任意精度数学函数和gmp函数都是   可用。有关“简单”的解释,请参阅»浮点指南   这也标题为“我的数字为什么不加起来?”

答案 1 :(得分:1)

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

echo decode(1.1710299640683E-305);

你不能使用 echo 函数的“圆形”和“人类可读”输出来解码原始值(因为你正在失去这个双精度)。

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

请参阅下面的示例,您也可以在http://www.compileonline.com/execute_php_online.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!
?>

答案 2 :(得分:0)

如果你有一个可靠的固定小数点,就像在我的情况下和货币的情况一样,你可以将浮动乘以10的幂(例如100美元)。

function encode($float) {
     return (int) $float * pow(10, 2);
}
function decode($str) {
    return bcdiv($str, pow(10, 2), 2);
}

但是,这不适用于大量数据,并没有正式解决问题。 似乎不可能从整数转换为浮点字符串并返回而不会丢失php 5.4中的原始整数值

相关问题