【问题标题】:Calculating Nth root with bcmath in PHP在 PHP 中使用 bcmath 计算第 N 个根
【发布时间】:2012-06-29 20:55:00
【问题描述】:

我们正在寻找 PHP 中的第 N 个根。我们需要对一个非常大的数字执行此操作,Windows 计算器返回 2。使用以下代码,我们得到 1。有人知道这是如何工作的吗?

echo bcpow(18446744073709551616, 1/64);

【问题讨论】:

  • 不起作用,因为 bcpow() 只接受整数指数。如果您只需要 64 次根,请改为使用 6 个平方根。

标签: php bcmath


【解决方案1】:

嗯,PHP 和 BC 库似乎有一些限制,在互联网上搜索后我发现了这个interesting article/code:

所以你应该使用这个函数:

<?php

function NRoot($num, $n) { 
    if ($n<1) return 0; // we want positive exponents 
    if ($num<=0) return 0; // we want positive numbers 
    if ($num<2) return 1; // n-th root of 1 or 2 give 1 

    // g is our guess number 
    $g=2; 

    // while (g^n < num) g=g*2 
    while (bccomp(bcpow($g,$n),$num)==-1) { 
        $g=bcmul($g,"2"); 
    } 
    // if (g^n==num) num is a power of 2, we're lucky, end of job 
    if (bccomp(bcpow($g,$n),$num)==0) { 
        return $g; 
    } 

    // if we're here num wasn't a power of 2 :( 
    $og=$g; // og means original guess and here is our upper bound 
    $g=bcdiv($g,"2"); // g is set to be our lower bound 
    $step=bcdiv(bcsub($og,$g),"2"); // step is the half of upper bound - lower bound 
    $g=bcadd($g,$step); // we start at lower bound + step , basically in the middle of our interval 

    // while step!=1 

    while (bccomp($step,"1")==1) { 
        $guess=bcpow($g,$n); 
        $step=bcdiv($step,"2"); 
        $comp=bccomp($guess,$num); // compare our guess with real number 
        if ($comp==-1) { // if guess is lower we add the new step 
            $g=bcadd($g,$step); 
        } else if ($comp==1) { // if guess is higher we sub the new step 
            $g=bcsub($g,$step); 
        } else { // if guess is exactly the num we're done, we return the value 
            return $g; 
        } 
    } 

    // whatever happened, g is the closest guess we can make so return it 
    return $g; 
}

echo NRoot("18446744073709551616","64");

?>

希望这对您有所帮助...

【讨论】:

  • 谢谢!奇迹般有效!我会给你+10,但我只能+1:P
【解决方案2】:

HamZa 的解决方案在任意精度下工作时遇到问题,所以我采用了一点。

<?php

function NthRoot($Base, $NthRoot, $Precision = 100) {
    if ($NthRoot <  1) return 0;
    if ($Base    <= 0) return 0;
    if ($Base    <  2) return 1;
    $retVal    = 0;
    $guess     = bcdiv($Base, 2, $Precision);
    $continue  = true;
    $step = bcdiv(bcsub($Base, $guess, $Precision), 2, $Precision);
    while ($continue) {
        $test = bccomp($Base, bcpow($guess, $NthRoot, $Precision), $Precision);
        if ($test == 0) {
            $continue = false;
            $retVal   = $guess;
        }
        else if ($test > 0) {
            $step  = bcdiv($step, 2, $Precision);
            $guess = bcadd($guess, $step, $Precision);
        }
        else if ($test < 0) {
            $guess = bcsub($guess, $step, $Precision);
        }
        if (bccomp($step, 0, $Precision) == 0) {
            $continue = false;
            $retVal   = $guess;
        }
    }
    return $retVal;
}

【讨论】:

    猜你喜欢
    • 2014-03-24
    • 2012-02-08
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多