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()
的行为方式。从来没有答案如何解决这个现实问题...
答案 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)
)。…和整数始终不能防止所有舍入错误(例如,单个项目的税额计算与发票总额的计算不匹配)。