【问题标题】:Does the issue with floating point precision only affect calculations?浮点精度问题是否只影响计算?
【发布时间】:2013-02-18 14:45:59
【问题描述】:

我有一些价格和折扣金额将存储在 PHP 代码的配置变量中。我想知道是否需要将它们存储为字符串。

例如,执行以下操作是否安全?

$price = 14.95;
$volume_discount = 0.3;

还是应该将它们存储为字符串?

$price = '14.95';
$volume_discount = '0.3';

我知道,除非您使用 BC Math,否则比较浮点数和使用浮点数进行计算会产生意想不到的结果。但我想知道是否按原样打印出存储的值。我尝试回显浮动版本,它们按预期显示,但我想知道这是否可靠。

注意:我用expected这个词来解释外行人的期望。正如 Eric 指出的那样,精确的十进制浮点数实际上不是预期的结果。

编辑:我目前关心的代码检查数量并确定是否应应用折扣。然后进行如下计算:

$price -= round($price * $volume_discount, 2);

我通常使用number_format 来格式化显示价格,但我注释掉了我的测试格式。到目前为止,无论价格或折扣值如何,PHP 都给了我想要的结果。然而,JavaScript 并不总能给我想要的结果。这就是让我再次查看我的 PHP 代码的原因。

显然,我将调整 JavaScript,因为这是错误出现的地方,但我试图决定是否需要重构我的 PHP 代码。

向我说明问题的数字是 149.95 * 0.3。 PHP 显示 44.985,JavaScript 显示 44.98499999999999。所以,即使四舍五入到小数点后两位,我得到的数字也不同。

【问题讨论】:

  • 取决于您将使用的代码。

标签: php floating-point


【解决方案1】:

解释十进制数字“14.95”并将其存储在二进制浮点对象中需要浮点运算:从十进制转换为二进制浮点。因此,这是一个浮点运算,存在舍入误差。

当源文本由编译器或解释器或在运行时解释时,可能会发生这种转换,但它确实会发生并且会出现舍入错误。

(您的问题断言与浮点数进行比较和计算会产生意想不到的结果。仅当您不期望操作遵守这些操作的规范时才如此。您可以通过学习规范来避免意外结果,因此了解会发生什么。)

【讨论】:

  • 那么在这种情况下精确显示值仅仅是巧合吗?我的脚本已经用正常的数学计算价格有一段时间了,我没有注意到任何舍入错误。直到现在我添加了 JavaScript 计算,我才注意到一个差异。有舍入误差的是 JavaScipt,而不是 PHP。
  • @toxalot:您还没有展示如何显示数字。当执行中等数量的操作并且数字以仅显示几位的格式显示时,舍入错误通常是不可见的,因为它们没有改变足够的值(从理想的数学结果)来改变显示的值。但是,用几个值,甚至很多值进行测试,并不足以保证其他值的错误不会导致这种变化。一般来说,确定长序列操作的良好错误界限是一个难题。
  • 所以我想到目前为止我很幸运,我需要确定舍入误差的(不)重要程度。
猜你喜欢
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-27
  • 2017-09-23
  • 1970-01-01
相关资源
最近更新 更多