php fmod返回无法使用的结果

时间:2018-07-15 14:44:03

标签: php modulo fmod

fmod(floatval("314.6"), floatval("1.3"))
=> 1.1990408665952E-14

我或多或少地理解了用二进制形式表示数字以及使用IEEE-754表示数字的潜在问题。但是:我将如何获得可用于实践的结果?

我要实现的示例:商家可以定义其产品的价格P,但是价格必须是x的倍数:

if (fmod(P, x) != 0) { echo "price must be a multiple of " . x; }

这是如此简单,但是只要我得到类似1234E-18的返回值fmod(),该方法就会失败。 在现实生活中如何在不使用自定义代码的情况下轻松检查价格区间?

这个问题或类似问题一直存在,但是我能找到的所有解释都是解释fmod()的行为方式。从来没有答案如何解决这个现实问题...

1 个答案:

答案 0 :(得分:0)

这里的问题是314.6恰好是1.3 * 242,所以浮点余数为零,但是由于您很清楚IEEE 754的错误,您得到0.00000000000001199041

但是请不要忘记浮点数学规则之一:您不能compare floats粗心地寻求平等。如果参数具有小数点后一位,则结果不需要14位精度。您有价格:您的货币中多少个小数才有意义?如果您使用的是欧元,您不太可能使用超过两个(美分)的货币,并且1.1990408665952E-14对所有影响而言均为零:

var_dump(round(1.1990408665952E-14, 2));
  

double(0)

有人建议使用整数(例如,以美分代替欧元)进行所有价格数学运算,以避免舍入误差,但大多数现实生活中的问题都来自非常具体的误差:

  • 向用户显示原始浮动(而不是四舍五入和格式化)。
  • 进行原始比较(if ($foo == $bar))。

…和整数始终不能防止所有舍入错误(例如,单个项目的税额计算与发票总额的计算不匹配)。