【问题标题】:PHP randomly decrements large integers by 1 [duplicate]PHP将大整数随机递减1 [重复]
【发布时间】:2016-01-03 07:46:05
【问题描述】:

我偶然发现了一个奇怪的错误/问题。

我有一个 MySQL 表,其中有一列填充了数字 (BIGINT)。这些数字对于常规的 32 位整数来说太大了,因此 PHP 会将它们转换为 32 位的字符串。这每次都会给出正确的结果。

在 64 位 PHP 上运行且不强制转换为带有 $variable = (string)$variable 的字符串时,结果有时会减 1,这样 1293203059233 之类的数字就会变成 1293203059232。这不好明显地。奇怪的是我看不到任何图案。

这不是随机发生的,MySQL 中的一行有时会递减,有时不会,而是相同的整数/行总是递减,并且总是递减 1。

是什么原因造成的?我使用json_encodestdClass-objects 或arrays() 转换为文本,然后通过常规HTTP 响应发送它们。

mysqli 使用准备好的语句检索行,例如:

$stmt = $sql->prepare->("SELECT BIGNUMBER FROM table WHERE SOMEID = ?");
$stmt->bind_result($bignumber);
$stmt->bind_param("i",$someid);
$stmt->execute();
$stmt->fetch();
$stmt->close();

$obj = new stdClass();
$obj->number = $bignumber;

echo json_encode($obj);

我在浏览数据库表时验证了所有整数都是正确的。

一些例子(这些是实际值):

不强制转换为字符串:

10205160559939609 -> 10205160669939608 // bad

与:

10205160559939609 -> "10205160559939609" // good

不强制转换为字符串:

10154493437278508 -> 10154493437278508 // good (?)

与:

10154493437278508 -> "10154493437278508" // good

编辑:我做了一个error_log测试pre-json_encode来测试,结果:

as Strng: (used error_log((string)$number);)
10205160559939609
as int: (used error_log($number);)
10205160559939609

这表明 php 确实得到了正确的值,并且错误发生在 php json_encode 或浏览器的 decode 方法中。

【问题讨论】:

  • @Martin PHP_INT_MAX 对于 64 位 PHP 是 9223372036854775807,大于 10205150669939609
  • 我的猜测是它与known issue with json_encode and large integers有关...你能用一个特定的整数和json_encode重现它吗?
  • @MattGibson 这些数字似乎也比 PHP_MAX_INT 大。至少在您链接的问题中。
  • 我可以将它们转换为字符串。幸运的是,在我的情况下,结果很好。它只是让我担心,如果我在某个时候遇到一个大整数,我的一些数学会出错。给我一分钟,我会从 json_encode 测试中得到一些结果。

标签: php mysql json


【解决方案1】:

只需在 chrome 控制台中输入 10205150669939609 即可打印出数字 10205150669939608(四舍五入效果)。我猜这么大的整数在 JS 中无效,所以它们也不应该在 JSON 中。如果我有这么大的值,我会使用字符串。

【讨论】:

  • 从 cmets 的所有讨论中,我希望这个答案会有点,嗯,更有教育意义。
  • 例如澄清问题不在于 PHP 本身,因为 PHP_INT_MAX 值大于使用的 int 值,并且问题特别是 JSON 封装,因为 javascript 认为所有数字都是浮动的而不是比整数。因此,当浮点数(DOUBLE)在 PHP 中恢复为 INT 类型时,这是一个舍入错误。
  • @Martin - “在 PHP 中恢复为 INT 类型。”。你的意思是“在 JavaScript 中”? PHP 对我的数字没有任何问题。
  • @nickdnk PHP没有问题,但是数值传递给JSON并存储在JSON系统中,这就是发生故障的地方,然后将数字传递回PHP(即非-javascript) 系统,然后由于 JS 使用浮点数而不是 INT,因此故障随之传递。 :)
  • 另外,@andrrs,请注意 JSON 不是类型感知的。它会将任何整数大小正确打印为整数,但 JavaScript 无法反序列化它。
猜你喜欢
  • 2017-12-21
  • 2015-07-15
  • 2015-06-23
  • 1970-01-01
  • 2017-08-20
  • 2017-07-25
  • 2011-06-23
  • 2014-12-06
  • 1970-01-01
相关资源
最近更新 更多