PHP 取模 vs PHP_INT_MAX 处的减法

PHP modulo vs substract at PHP_INT_MAX

在某些时候我有这段代码:

while( $i> $l-1 )
{
    $x= fmod($i,$l);
    $i= floor($i/$l);
}

我决定摆脱模运算并写下这个块:

while( true )
{
    $d= floor( $i/$l );
    if( $d>= 1 )
    {
        $x= $i - ($d*$l);
        $i= $d;
    }
    else
    {
        break;
    }
}

$x 用于索引长度为 $l 的数组。 $i 在这里有问题。

虽然对于一些相对较小的初始 $i,两个块在所有迭代中给出相同的 $x,当用接近 PHP_INT_MAX 的东西初始化时,两个块不给出相同的 $x。

不幸的是,$l 不能成为 2 的幂以便使用位运算符,所以我受困于此。

我猜这与发生的内部四舍五入有关。 fmod 可以针对这种情况进行如此优化吗?有什么我没看到的吗?

接受@trincot 的回答后的补充评论。

我应该提到的一件事是,虽然人们希望第二种方法产生更好的结果,但由于使用简单的减法,它没有。可能是因为除法发生在循环的开始。(这就是为什么我问“fmod 可以这么优化吗”)。

根据文档,fmod 适用于浮点数:

fmod — Returns the floating point remainder (modulo) of the division of the arguments

相反,modulo operator (%) 更适合您的需要:

Operands of modulus are converted to integers (by stripping the decimal part) before processing.

fmod 对于大整数将变得不准确,因为浮点表示不具有相同的精度。

发生的一些奇怪的例子:

$l=3;
$i=9223372036854775295;
echo is_int($i) . "<br>"; // 1 (true)
echo (9223372036854775295==$i) . "<br>"; // 1 (true)
echo number_format($i, 0, ".", "") . "<br>"; // 9223372036854774784
echo fmod($i,$l) . "<br>";   // 1
echo fmod($i-1,$l) . "<br>"; // 1
echo fmod($i-2,$l) . "<br>"; // 1
echo ($i % $l) . "<br>";     // 2
echo (($i-1) % $l) . "<br>"; // 1
echo (($i-2) % $l) . "<br>"; // 0

注意一个简单的 number_format 已经破坏了整数的精度;由于浮点转换,它 return 是一个不同的数字。

另请注意,这种精度的缺乏使得三个连续数字的 fmod return 为 1,而模运算符会执行您想要的操作。

所以你看起来更适合 %

备选

您的函数似乎在 L 基中将数字分解为其“数字”。例如,当 $l=2 时,您的 $x 序列会生成数字的二进制表示,但您遗漏的最后一位数字除外。

在这方面,您可以查看函数调用 base_convert($i,10,$l),它会生成对应于代码中值 $x 的一位数字,其中数字大于 9 的字母。函数最多可以接受 $l 36 个值。