gpt4 book ai didi

php intval() 和 Floor() 返回值太低?

转载 作者:行者123 更新时间:2023-12-03 00:30:48 27 4
gpt4 key购买 nike

由于 PHP 中的 float 数据类型不准确,并且 MySQL 中的 FLOAT 比 INT 占用更多空间(并且不准确),因此我总是将价格存储为 INT,在存储之前乘以 100,以确保精确到小数点后 2 位精确的地方。但我认为 PHP 行为不当。示例代码:

echo "<pre>";

$price = "1.15";
echo "Price = ";
var_dump($price);

$price_corrected = $price*100;
echo "Corrected price = ";
var_dump($price_corrected);


$price_int = intval(floor($price_corrected));
echo "Integer price = ";
var_dump($price_int);

echo "</pre>";

产生的输出:

Price = string(4) "1.15"
Corrected price = float(115)
Integer price = int(114)

我很惊讶。当最终结果比预期低 1 时,我期望测试的输出看起来更像是:

Price = string(4) "1.15"
Corrected price = float(114.999999999)
Integer price = int(114)

这将证明 float 类型的不准确性。但为什么 Floor(115) 返回 114?

最佳答案

尝试将此作为快速修复:

$price_int = intval(floor($price_corrected + 0.5));

您遇到的问题不是 PHP 的错,所有使用实数和浮点运算的编程语言都有类似的问题。

货币计算的一般经验法则是永远不要使用 float (无论是在数据库中还是在脚本中)。您可以通过始终存储美分而不是美元来避免各种问题。分是整数,您可以自由地将它们相加,并乘以其他整数。每当显示数字时,请确保在最后两位数字前面插入一个点。

您得到 114 而不是 115 的原因是 floor 向最接近的整数向下舍入,因此 Floor(114.999999999) 变为 114。更有趣的问题是为什么 1.15 * 100 是 114.999999999而不是 115。原因是 1.15 并不完全是 115/100,但它要小一些,所以如果乘以 100,就会得到一个比 115 小一点点的数字。

以下是 echo 1.15 * 100; 作用的更详细说明:

  • 它将 1.15 解析为二进制 float 。这涉及到四舍五入,正好向下舍入一点,得到最接近1.15的二进制 float 。无法获得精确数字(没有舍入误差)的原因是 1.15 在 2 进制下有无限多个数字。
  • 它将 100 解析为二进制 float 。这涉及到舍入,但由于 100 是一个小整数,所以舍入误差为零。
  • 它计算前两个数字的乘积。这还涉及一点舍入,以找到最接近的二进制 float 。此操作中舍入误差恰好为零。
  • 它将二进制 float 转换为带点的以 10 为基数的十进制数,并打印此表示形式。这还涉及一点舍入。

PHP 打印令人惊讶的 Corrected Price = float(115) (而不是 114.999...)的原因是 var_dump 不打印确切的数字 ( !),但它会打印四舍五入为 n - 2 (或 n - 1)位的数字,其中 n 位是计算的精度。您可以轻松验证这一点:

echo 1.15 * 100;  # this prints 115
printf("%.30f", 1.15 * 100); # you 114.999....
echo 1.15 * 100 == 115.0 ? "same" : "different"; # this prints `different'
echo 1.15 * 100 < 115.0 ? "less" : "not-less"; # this prints `less'

如果您要打印 float ,请记住:打印 float 时您并不总是能看到所有数字

另请参阅 PHP float 开头附近的大警告文档。

关于php intval() 和 Floor() 返回值太低?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/812815/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com