【问题标题】:PHP intval() changes number NOT 2147483647PHP intval() 更改编号 NOT 2147483647
【发布时间】:2014-12-31 13:19:37
【问题描述】:

我正在运行 PHP 5.3.13,当我执行时

php -r "echo intval(9999999999);"

它输出 141006540​​7。

当我执行时

php -r "echo intval(PHP_INT_MAX);"

它输出 2147483647。

较小的整数导致我的代码出现一些问题。为什么有区别?

【问题讨论】:

标签: php 32-bit


【解决方案1】:

在您的情况下,值9999999999 被存储为float。您可以使用var_dump(9999999999) 验证这一点。当它被转换为一个有符号整数时,该值被截断为 32 位,这给出了值 1410065407

您可以手动或使用 GMP 数学扩展验证此计算:

$num = gmp_init("9999999999");
$bits = gmp_pow(2, 32);

var_dump(gmp_strval(gmp_mod($num, $bits)));
// string(10) "1410065407"

【讨论】:

  • 啊哈,说得有道理。我会接受的。感谢您的明确答复
  • 请解释您的计算。因为(9999999999 % 2147483647) 对我来说是14100654119999999999 = 4 * 2147483647 + 1410065411。但是:(9999999999 & 2147483647) = 1410065407
  • 那么你应该编辑你的答案,因为 PHP_INT_MAX 实际上是 2147483647 在 32 位系统上。所以计算是错误的(无论如何不可能在32位系统上解决)
  • @BreyndotEchse - 你完全正确。这不是模数PHP_INT_MAX,而是模数2^32。模数 PHP_INT_MAX 忽略 ~2^31 负有效整数值。我已经更新了我的答案。
【解决方案2】:
9999999999 (base 10) = 10|01010100000010111110001111111111 (base 2)
1410065407 (base 10) =   |01010100000010111110001111111111 (base 2)
                         ^
                         ------------ 32 bits ------------

前两个most significant bits 被删除。然后你得到 141006540​​7 (base 10)

【讨论】:

    【解决方案3】:

    整数9999999999的二进制表示为:

    0010 0101 0100 0000 1011 1110 0011 1111 1111
    

    这意味着您需要超过 32 位来表示该数字。如果您使用的是 32 位架构,则该数字将被截断为

    0101 0100 0000 1011 1110 0011 1111 1111
    

    代表整数141006540​​7,函数返回的值。

    【讨论】:

      【解决方案4】:

      您的号码太大并导致溢出。 PHP 整数是无符号的 32 位整数。如果您想处理大量数字,可以查看BCMath

      【讨论】:

        猜你喜欢
        • 2010-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-14
        • 2011-11-16
        • 2013-07-24
        • 1970-01-01
        相关资源
        最近更新 更多