尝试在x64体系结构上重现dechex()函数行为

时间:2013-03-08 06:27:22

标签: php 64-bit hex base-conversion

dechex()函数PHP manual page的示例#2如下:

// The output below assumes a 32-bit platform.
// Note that the output is the same for all values.
echo dechex(-1)."\n";
echo dechex(PHP_INT_MAX * 2 + 1)."\n";
echo dechex(pow(2, 32) - 1)."\n";

以上示例将输出:

ffffffff
ffffffff
ffffffff

我试图在x64系统上重现这种行为:

echo dechex(-1)."\n";
echo dechex(PHP_INT_MAX * 2 + 1)."\n";
echo dechex(pow(2, 64) - 1)."\n";

我期待:

ffffffffffffffff
ffffffffffffffff
ffffffffffffffff

但是,我明白了:

ffffffffffffffff
0
0

知道这里发生了什么?

2 个答案:

答案 0 :(得分:0)

首先,重要的是要注意PHP dechex函数需要整数输入。

在64位系统上,PHP不支持64位整数。

例如,64位系统上的典型PHP_INT_MAX是:

 9223372036854775807

这也是dechex可以接受的最大整数(!)数。

如果传入pow(2, 64) - 1,则转换为整数的浮点数(1.844674407371E+19)为整数0,因此dechex返回字符串"0"

如果您将2 ^ 64作为字符串"18446744073709551615"传入,则同样适用。它被转换为整数,在64位系统上它的整数值为9223372036854775807。因此dechex返回字符串"7fffffffffffffff"

因此,如果您需要处理这些数字,则不能使用PHP的整数类型,因此dechex不适合该作业。相反,你可以使用bcmath和gmp函数来实现你想要的东西:

echo gmp_strval(bcadd(bcmul(2, PHP_INT_MAX), 1), 16), "\n";
echo gmp_strval(bcsub(bcpow(2, 64), 1), 16), "\n";

答案 1 :(得分:0)

我怀疑在64位平台上有一个dechex的错误,这个错误与可存储为浮点数的最大整数是pow(2,53)-1,即9007199254740991这个事实有关。该手册确实警告过使用base_convert使用非常大的数字,因为你可以使用浮点数,并且浮点系统不精确的b / c可能会出现奇怪的结果。 dechex可能会出现类似情况。

PHP接受一个数字作为dechex的参数,它可以是整数或浮点数,但浮点数实际上只是表示溢出int边界的整数的设备。事实上,您在32位平台上成功运行的代码也传递给dechex一个超过32位平台的最大整数值的值,传入一个浮点数,如下面的注释所示:

<?php

echo "Max int: ",PHP_INT_MAX, "\n"; // Max int: 2147483647
$num = (PHP_INT_MAX * 2) + 1;
var_dump($num);   //                // float(4294967295)
echo dechex($num),"\n";            // ffffffff
echo dechex(-1);                   // ffffffff

您可能希望在bugs.php.net上提交错误报告。