有什么办法在PHP中获得浮点数的二进制表示?像Java的Double.doubleToRawLongBits()。如何在PHP中获取浮点数的二进制表示?
给定一个正的浮点数,我想得到最大的可表示的浮点数小于该数。在Java中,我可以这样做:
double x = Double.longBitsToDouble(Double.doubleToRawLongBits(d) - 1);
但我没有看到任何类似的PHP。
有什么办法在PHP中获得浮点数的二进制表示?像Java的Double.doubleToRawLongBits()。如何在PHP中获取浮点数的二进制表示?
给定一个正的浮点数,我想得到最大的可表示的浮点数小于该数。在Java中,我可以这样做:
double x = Double.longBitsToDouble(Double.doubleToRawLongBits(d) - 1);
但我没有看到任何类似的PHP。
这不是一个完整的答案,但我知道的唯一办法浮法成二进制是pack()
这里是我想出了利用Peter Bailey的建议的解决方案。它需要64位版本的PHP。我不认为这是以任何方式生产质量,但我分享,以防任何人想要建立它。 (事实上,我结束了做不同的事情完全是我张贴的问题后,但我在这里把它作为一种智力活动。)
// Returns the largest double-precision floating-point number which
// is less than the given value. Only works for positive values.
// Requires integers to be represented internally with 64 bits (on Linux
// this usually means you're on 64-bit OS with PHP built for 64-bit OS).
// Also requires 64-bit double-precision floating point numbers, but I
// think this is the case pretty much everywhere.
// Returns false on error.
function prevDouble($d) {
$INT32_MASK = 0xffffffff;
if((0x1deadbeef >> 32) !== 1) {
echo 'error: only works on 64-bit systems!';
return false;
}
if($d <= 0) {
return false;
}
$beTest = bin2hex(pack('d', 1.0)); //test for big-endian
if(strlen($beTest) != 16) {
echo 'error: system does not use 8 bytes for double precision!';
return false;
}
if($beTest == '3ff0000000000000') {
$isBE = true;
}
else if($beTest == '000000000000f03f') {
$isBE = false;
}
else {
echo 'error: could not determine endian mode!';
return false;
}
$bin = pack('d', $d);
//convert to 64-bit int
$int = 0;
for($i = 0; $i < 8; $i++)
$int = ($int << 8) | ord($bin[$isBE ? $i : 7 - $i]);
$int--;
//convert back to double
if($isBE)
$out = unpack('d', pack('N', ($int >> 32) & $INT32_MASK) . pack('N', $int & $INT32_MASK));
else
$out = unpack('d', pack('V', $int & $INT32_MASK) . pack('V', ($int >> 32) & $INT32_MASK));
return $out[1];
}
作为一个附加的应答不整的问题,但到标题:
如果你想看到你的彩车的样子为二进制:
输出:
0011100010001010100101011010010110110111111110000111101000001111
0011111111010000000000000000000000000000000000000000000000000000
0011111111100000000000000000000000000000000000000000000000000000
1011111111100000000000000000000000000000000000000000000000000000
的java:
long lnBits = Double.doubleToLongBits(longValue);
Byte[] bits = new byte [] {
(byte) ((value << 56) >>> 56),
(byte) ((value << 48) >>> 56),
(byte) ((value << 40) >>> 56),
(byte) ((value << 32) >>> 56),
(byte) ((value << 24) >>> 56),
(byte) ((value << 16) >>> 56),
(byte) ((value << 8) >>> 56),
(byte) (value >>> 56)}
PHP:
$bits = $bitsFromJava;
$str="";
for($i=0;$i<8;i++){
$str.=chr($bits[$i]);
}
$longValue=unpack('d',$str);
$bitsToJava=array();
for(str_split(pack($longValue)) as $chr){
$bitsToJava[]=ord($chr);
}
我敢肯定你的Java代码是马车。只有低位被设置时会发生什么?我怀疑忽略指数不起作用......或者当你从指数0到-1,你是否破坏了NaN等位? – derobert 2011-01-19 00:15:23
@derobert:如果你可以发现我的Java代码不工作的情况,除了±0,±Inf或NaN,让我知道(用负值给出的最小值大于给定值)。将正IEEE浮点数转换为整数时,将被排序。 (负值是逆向排序的)。指数存储为带有偏移量的无符号值,而不是二进制补码,所以-1实际上是1小于0.如果只设置了低位,则您查看Double.MIN_VALUE的等效值,然后减1得到0 ,这是正确的答案。 – Jenni 2011-01-19 02:00:44
关于此的一篇非常好的文章可以在这里找到:http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm – Jenni 2011-01-19 02:01:16