64位浮点文字PHP


64-bit Float Literals PHP

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

在php文档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];
}

这在很大程度上起到了很好的作用。。。

echo decode(encode(10000000000000));

100000000

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

$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函数是可获得的有关"简单"的解释,请参阅»浮点指南这也是题为"为什么我的数字不加起来?">

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

echo decode(1.1710299640683E-305);

你不能使用"四舍五入";以及";人类可读的";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!
?>

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

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

然而,这对庞大的数字不起作用,也不能正式解决问题。似乎不可能在不丢失php 5.4 中的原始整数值的情况下从整数转换为浮点字符串并返回。