PHP模数与减去PHP_INT_MAX

时间:2015-12-23 13:51:12

标签: php arrays modulo subtraction fmod

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

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可以如此优化)。

1 个答案:

答案 0 :(得分:1)

根据文档,fmod适用于花车:

  

fmod - 返回参数除法的浮点余数(模数)

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

  

在处理之前,模数的操作数被转换为整数(通过去除小数部分)。

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如何破坏整数的精度;由于浮点转换,它返回不同的数字。

另请注意,这种精确度的缺失会导致fmod连续三个数字返回1,而模运算符会执行您想要的操作。

所以你似乎对%好多了。

替代

您的功能似乎将数字分解为&#34;数字&#34;以L为基础。例如,当$l=2时,您的$x - 序列生成数字的二进制表示形式,除了您遗漏的最后一位数字。

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