PHP 提供了不同的计算模数的函数:
应该使用哪个功能被认为是安全有效的?考虑到此处描述的(除零问题:使用模数和浮点数时除以零错误?
只有模数运算符 (%) 和 fmod 是原生的
模数运算符无法处理超出的数字2^32
(在运行 x86 架构的 PHP 上)
fmod 运行速度比 bcmod/gmp_mod 快~ benchmark
bcmod 不适用于浮点数 ~这里
我相信最好使用fmod
,因为它在Math Functions中,运行速度比其他函数快,最重要的是,可以处理大数字和浮点数。
如果您不打算使用超过限制或浮点数的数字,请使用%
它应该是最快的。
只要知道在做什么,所有功能都可以安全使用:
模数运算符:快速、精确,但您需要保持在最大 int 之下。在这个条款中,没有任何除以零的问题。
fmod:仍然很快,浮点运算速度在过去 10 年不再是问题,但很棘手。浮点数可以达到更高的值,但它们的精度不能。因此,使用大数字将越来越多地引入舍入误差。所以不会解决模运算符所缺乏的任何东西,而是会引入精度问题。
bcmod 和 gmp_mod 是相似的。不同之处在于此函数使用任意精度算术的不同实现(模块)。它们的用法不同,但结果不同:理论上,此库支持的数字大小仅受可用内存量的限制,因此实际上结果总是很好且精确,但是使用的算法在计算上和从记忆的角度。
您仍然可以使用模数运算符,并且如果您计划在某个时候期望为零,它仍然是安全的,如下所示。
if ($y > 0) {
// Do the calculation
}
else {
// Do this instead
}
仅仅隐藏警告也可以使用错误控制运算符。通过使用@
运算符,可以抑制错误。
然而,%
整数在转换为浮点数之前只能变得如此之大,因此引入了bcmod和fmod但请注意它们都有自己的局限性。
我会推荐GMP或者看看其他增强的数学函数之一,还有BCMath
既然你提到了一些安全的东西,那么有一个课程: Eval Math
这是一个使用示例fmod
<?php
echo fmod('4294967296', 34);
?>
输出18
请注意, fmod 不等同于此基本功能:
<?php
function modulo($a, $b) {
return $a - $b * floor($a / $b);
}
?>
因为 fmod() 将返回一个与 $a 符号相同的值。换句话说, floor() 函数不正确,因为它朝 -INF 舍入而不是朝零舍入。
要模拟 fmod($a, $b) 正确的方法是:
<?php
function fmod($a, $b) {
return $a - $b * (($b < 0) ? ceil($a / $b) : floor($a / $b)));
}
?>
请注意,如果 $b 为空,这两个函数都将抛出除零。
上面的第一个函数 modulo() 是数学函数,可用于处理循环结构(例如日历计算或三角函数:
- fmod($a, 2*PI) returns a value in [0..2*PI) if $a is positive
- fmod($a, 2*PI) returns a value in [-2*PI..0] if $a is negative
- modulo($a, 2*PI) returns a value always in [0..2*PI) independantly of the sign of $a