【问题标题】:PHP subtracting numbers strangely - returning long float valuesPHP奇怪地减去数字 - 返回长浮点值
【发布时间】:2013-11-26 04:20:39
【问题描述】:

我正在计算某些东西的费用(货币),而当金额应该为 0.00 时,PHP 的行为很奇怪。它将最终结果作为浮点数给出,而不是应该是 0。

在我的数据库中,我有下表

id   |  transaction_total   |    charge_fees   |  deposit_fee   |   amount_to_customer   |   fees_minus_total_difference

所以当我去检查以确保费用 + 支付金额 - 总计 = 0.00

(96.54 + .25 + 3.20 - 99.99) = 1.4210854715202E-14

为什么结果是浮点数而不是实际为零?这些数字原本是更多的小数位,但我使用 number_format 将其放入 2 位。例如,收费实际上可能是 3.19987

number_format(3.19971,2,'.','')  //equals 3.20

当我将它保存在我的数据库中时,它显示为 3.20。当我在计算总额/费用检查中使用它时,结果不为零,尽管接近。

【问题讨论】:

  • 永远不要将浮点数用于货币价值,除非您不介意损失少量金钱(或可能获得一些)。以美分计算或使用 bcmath 等任意精度库计算。
  • PHP Math Precision的可能重复

标签: php


【解决方案1】:

计算机以二进制形式存储数字,因此当您尝试表示十进制数字时,您可能会丢失精度。这就是这里发生的事情。

有些语言具有精确精度类型,但不幸的是,PHP 没有。不过,它确实为您提供了BC MathGMP。不过,在这里使用这些似乎有点过头了。使用 BC,您可以这样做:

bcsub(bcadd(bcadd('96.54','0.25',2),'3.20',2),'99.99',2) = 0

请注意,您还必须在此处指定小数位数 (2)。

通常,不赞成使用浮点数和双精度数进行财务处理,但使用 PHP 似乎是更简单的选择。我建议您使用 round() 将您的数字四舍五入到您输入的小数位数。

round(96.54 + .25 + 3.20 - 99.99,2) = 0

【讨论】:

  • 您需要将数字作为字符串提供给 bc 函数。只是在你的源代码中写0.12345 已经让你失去了精度。应该是bcadd('1.234', '5.678')
【解决方案2】:

我建议不要使用number_format() 来显示字符串。请改用round()

您的问题是浮点数。 PHP 有更精确的数学函数,您可以查看 bcadd、bcmul、bcdiv 等...

http://php.net/manual/en/book.bc.php

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多