用于比较PHP中浮点相等性的公式
如何比较浮点数
has been answered here的问题.这个问题的不同之处在于我在询问公式.两个最高投票的答案对问题的解决方案略有不同:
if (abs(($a-$b)/$b) < $epsilon) { … } 和 if (abs($a-$b) < $epsilon) { … } 为什么第一个答案包含分区?它不会导致不准确的结果吗?例如(使用简单数字),让$a和$b都等于0.01,并假设$a – $b得到0.0001,$epsilon为0.001. ((((0.01 - 0.01) == 0.0001) / 0.01 == 0.01) < 0.001) : false 而 (((0.01 - 0.01) == 0.0001) < 0.001) : true 我的数学可能有点生疏,但我错过了什么? 我什么时候应该使用一个公式而不是另一个? 解决方法
这可能允许用相对误差而不是绝对误差来检查epsilon.
比较这两种情况: function areEqual(float $a,float $b) : bool { return abs(($a - $b) / $b) < 0.00001; } areEqual(10000,10000.01); areEqual(0.0000001,0);
现在你已经可以看出差异了. 对于大数字:如果比较的浮点数非常大,则epsilon可能太小.浮点数内部只能存储一定数量的精度数字,而指数可能大于数字.结果,浮点错误的来源,即浮点数的最终数字,将出现在可能高于单位数的某处.换句话说,对于极大的浮点数,绝对误差可以大于1,远小于0.00001的epsilon. 对于小数字:这更为明显.这两个数字都已经小于epsilon.即使你将它们与0进行比较,虽然相对误差是无限大的,但你仍然认为它们是相等的.对于这种情况,您要么将两个操作数相乘,要么减少epsilon.它们实际上是相同的,但就实现而言,将差异除以其中一个操作数更为方便,这些操作数将乘以小数(/ 0.0001相当于* 10000)或向下除以大数(/ 10000,而差异希望小于10000) 此检查还有另一个名称.虽然abs($a – $b)被称为绝对误差,但我们通常使用相对误差,即绝对误差& div;近似值.因为这些值也可能是负数,所以我们绝对是全部($a – $b)/ $b.在这种情况下,我们的“epsilon”,0.00001意味着我们的容忍相对误差为0.00001,即0.001%误差. 请记住,这仍然不是绝对安全的.在程序中进行多次转换之后,例如,您可以使用一些大数字来添加/乘以数字,然后再次减去数字,将大数字中的不纯错误留给人类仍然可以忽略不计,但值得注意你的epsilon值.因此,在选择epsilon值或浮点比较算法之前,请务必三思而后行. 作为最佳做法,避免使用小数字添加,减去或乘以大数字.他们会增加错误的机会.在开发(特别是简化)算法时,始终要考虑到它们可能是浮点数中的错误.这可能会将工作量增加到一个愚蠢的程度,但只要你意识到这一点,这种担心有时可以避免你被踢出团队. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |