将 JavaScript 函数转换为 PHP

szm*_*gma 7 javascript php

我有一个带有数组输入的 JS 函数。

例如:

x=[ 239709880, 250229420, 109667654, 196414465, 13098]
y=[ 78135241, 54642792, 249]

或者:

x=[ 0, 0, 0, 0, 0, 0, 1 ]
y=[ 78135241, 54642792, 249 ]

或者:

x=[ 49 ]
y=[ 33 ]

function bdiv(x,y) {
    var n=x.length-1, t=y.length-1, nmt=n-t, arr = []
    if(n < t || n==t && (x[n]<y[n] || n>0 && x[n]==y[n] && x[n-1]<y[n-1])) {
        arr['q']=[0]
        arr['mod']=x
        return arr
    }
    if(n==t && toppart(x,t,2)/toppart(y,t,2) <4) {
        var q=0, xx
        for(;;) {
            xx=bsub(x,y)
            if(xx.length==0) break
            x=xx; q++
        }
        arr['q']=[q]
        arr['mod']=x
        return arr
    }
    var shift, shift2
    shift2=Math.floor(Math.log(y[t])/log2)+1
    shift=bs-shift2

    if(shift) {
        x=x.concat()
        y=y.concat()
        for(i=t; i>0; i--) y[i]=((y[i]<<shift) & bm) | (y[i-1] >> shift2); y[0]=(y[0]<<shift) & bm
        if(x[n] & ((bm <<shift2) & bm)) { x[++n]=0; nmt++; }
        for(i=n; i>0; i--) x[i]=((x[i]<<shift) & bm) | (x[i-1] >> shift2); x[0]=(x[0]<<shift) & bm
    }
    var i, j, x2, y2,q=zeros(nmt+1)

    y2=zeros(nmt).concat(y)

    for(;;) {
        x2=bsub(x,y2)
        if(x2.length==0) break
        q[nmt]++
        x=x2
    }
    var yt=y[t], top=toppart(y,t,2)
    for(i=n; i>t; i--) {
        m=i-t-1
        if(i >= x.length)
            q[m]=1
        else if(x[i] == yt)
            q[m]=bm
        else
            q[m]=Math.floor(toppart(x,i,2)/yt)
        topx=toppart(x,i,3)
        while(q[m] * top > topx)
            q[m]--
        y2=y2.slice(1)
        x2=bsub(x,bmul([q[m]],y2))
        if(x2.length==0) {
            q[m]--
            x2=bsub(x,bmul([q[m]],y2))
        }
        x=x2
    }
    if(shift){
        for(i=0; i<x.length-1; i++)
            x[i]=(x[i]>>shift) | ((x[i+1] << shift2) & bm);
        x[x.length-1]>>=shift
    }
    while(q.length > 1 && q[q.length-1]==0)
        q=q.slice(0,q.length-1)
    while(x.length > 1 && x[x.length-1]==0)
        x=x.slice(0,x.length-1)
    arr['q']=q
    arr['mod']=x
    return arr;
}
Run Code Online (Sandbox Code Playgroud)


到目前为止我在 PHP 中做了不到 5 天的工作:

function bdiv($x,$y){
    global $bs, $bm, $bx2, $bx, $bd, $bdm, $log2;
    $arr=[];
    $n=count($x)-1;
    $t=count($y)-1;
    $nmt=$n-$t;

    if($n < $t || $n==$t && ($x[$n]<$y[$n] || $n>0 && $x[$n]==$y[$n] && $x[$n-1]<$y[$n-1]))
        return ['q'=>[0], 'mod'=>$x];

    if($n==$t && toppart($x,$t,2)/toppart($y,$t,2) <4){
        $q=0;
        for(;;){
            $xx=bsub($x,$y);
            if(count($xx)==0)
                break;
            $x=$xx;
            $q++;
        }
        return ['q'=>[$q], 'mod'=>$x];
    }

    $shift2=floor(log($y[$t])/$log2)+1;
    $shift=$bs-$shift2;
    if($shift){

/////////////////////////////////////////////// Booboo
        //$x = array_merge(array(),$x);
        //$y = array_merge(array(),$y);

        for($i=$t; $i>0; $i--)
            $y[$i]=(($y[$i] << $shift) & $bm) | ($y[$i-1] >> $shift2);
        $y[0]=($y[0] << $shift) & $bm;
        if($x[$n] & (($bm << $shift2) & $bm)){
            $x[++$n]=0;
            $nmt++;
        }
        for($i=$n; $i > 0; $i--)
            $x[$i]=(($x[$i] << $shift) & $bm) | ($x[$i-1] >> $shift2);
        $x[0]=($x[0] << $shift) & $bm;
    }
    $q=zeros($nmt+1);

    //array_push($arr, zeros($nmt));
    //array_push($arr, $y);
    //$y2=array_merge(...$arr);
    //////////////////////////////////// use array_merge straight away
    $y2=array_merge(zeros($nmt),$y);

    for(;;){
        $x2=bsub($x,$y2);
        if(count($x2)==0)
            break;
        $q[$nmt]++;
        $x=$x2;
    }

    $yt=$y[$t];
    $top=toppart($y,$t,2);

    for($i=$n; $i>$t; $i--){
        $m=$i-$t-1;
        if($i >= count($x))
            $q[$m]=1;
        else if($x[$i] == $yt)
            $q[$m]=$bm;
        else
            $q[$m]=floor(toppart($x,$i,2)/$yt);

        $topx=toppart($x,$i,3);
        while($q[$m] * $top > $topx)
            $q[$m]--;

        $y2=array_slice($y2,1);
        $x2=bsub($x,bmul([$q[$m]],$y2));

        if(count($x2)==0){
            $q[$m]--;
            $x2=bsub($x,bmul([$q[$m]],$y2));
        }
        $x=$x2;
    }

    if($shift){
        for($i=0; $i<count($x)-1; $i++)
            $x[$i]=($x[$i] >> $shift) | (($x[$i+1] << $shift2) & $bm);
        $x[count($x)-1] >>= $shift;
    }

    while(count($q) > 1 && $q[count($q)-1]==0)
        $q=array_slice($q, 0, count($q)-1);
    while(count($x) > 1 && $x[count($x)-1]==0)
        $x=array_slice($x, 0, count($x)-1);

    return ['q'=>$q, 'mod'=>$x];
}
Run Code Online (Sandbox Code Playgroud)

因此,正如我在 PHP 代码中标记的那样,我对array_push($x,$x)有问题,似乎这并不等同于x=x.concat()。Array_push 将整个当前 $x 值作为新元素添加到现有$x数组中:

$x=[ 1, 2, 3 ];
array_push($x,$x);
那么 $x 将是 [ 1, 2, 3, [ 1, 2, 3 ] ]

如果我尝试展平数组($x=array_merge(...$x);),则会出现一个新的 PHP 错误:array_merge(): Argument #1 is not an array

如果有人知道如何将此 JS 函数正确转换为 PHP 版本,我将非常感激。提前致谢。

==========================> 更新我

@Kiran Shakya 想法用 $x=array_merge(array(),$x) 替换 x=x.concat() ;实际上正在工作,或者至少我没有收到任何 PHP 错误或警告,但启动了一个无限循环,我必须手动关闭它。调用 toppart 函数的脚本,该函数以任意精度数字进行运算(乘法和加法):

    function toppart(x,start,len) {
        var n=0
        while(start >= 0 && len > 0){
            n=n*bx2+x[start--]
            len--
        }
        return n
    }
Run Code Online (Sandbox Code Playgroud)

有趣的是,JS 返回了一个示例 70144566321522750,但 PHP 返回了 70144566321522751。在后面的循环中,差异更大。
我已经检查了两个版本中的所有数字和所有相同的输入:x,start,len,bx2。这可能是一个错误,或者其中之一无法处理大整数,或者原因是什么?

==========================> 更新二

我应用了 Booboo 解决方案,我只是完全跳过了 concat() 部分

所以输入是:

$x=[ 210763776, 109357119, 261308872];
$开始=2;
$len=2;
$bx2=268435456;

...并在 PHP 中返回 70144566321522751,在 JS 中返回 70144566321522750。我使用 bcadd() 和 bcmul() 但如果我使用数学运算符号,结果是相同的。

function toppart($x,$start,$len){
    global $bs, $bm, $bx2, $bx, $bd, $bdm, $log2;
    $n=0;
    while($start >= 0 && $len > 0){
        $n= bcadd(bcmul($n, $bx2),$x[$start--]);
        $len--;
    }

    return $n;
}
Run Code Online (Sandbox Code Playgroud)

San*_*aus 1

将 array_push 替换为 array_merge。

这将返回合并后的数组,然后将结果存储在 $x 中;

array_merge 适用于数组。它将从一个数组中获取值并将其附加到另一个数组中。就像 JS 中的 concat 一样。

...将数组 ($x) 拆分为多个值,这不是正确的输入。它相当于 array_merge(1,2,3) (即没有输入数组)

$x = array(1,2,3);
$x = array_merge($x,$x);
var_dump($x); //output: [1,2,3,1,2,3]

echo $x[4]; // output: 2

Run Code Online (Sandbox Code Playgroud)

如果我误解了这个问题,请告诉我。