【问题标题】:Working with giant numbers in PHP在 PHP 中处理巨大的数字
【发布时间】:2013-10-01 15:49:45
【问题描述】:

早安。 我正在寻找一种方式/扩展,以便我可以在 PHP 中使用非常大的数字计算 FAST,例如与 50 位数字相乘。

请不要告诉我,我将使用 BC Math 或 GMP。 他们是我的第二个想法, 但两者都如此无用,当结果超过 38 位时都只返回“false”。

我已经尝试过编写自己的计算函数,这实际上是有效的,但我相信它有点慢。 它将数字的每一个数字都保存在一个数组中,并且像我在小学时学到的那样进行计算。

只有当传入的数字也是数组时,它才能完美运行。 因为否则计算机会在他保存它们之前破坏它们。

有没有办法让我的函数更快一点,或者是否存在一个真正用大数字计算的库?

function multiplicate($A, $B)
{
    if (!is_array($A))
    {
        $A = preg_split("//", strval($A), -1, PREG_SPLIT_NO_EMPTY);
    }
    if (!is_array($B)) 
    {
        $B = preg_split("//", strval($B), -1, PREG_SPLIT_NO_EMPTY);
    }

    if ( $A[0]=='-') 
    {
        array_splice($A, 0, 1);
        $negA=-1;
    }
    else 
    {
        $negA=1;
    };
    if ( $B[0]=='-') 
    {
        array_splice($B, 0, 1);
        $negB=-1;
    }
    else 
    {
        $negB=1;
    };

    $l = 0;
    $m = 0;
    $Erg[0] = 0;

    for ( $i=0; $i < count($A); $i++) 
    {
        for ( $j=0; $j < count($B); $j++) 
        {
            $ZwErg = preg_split("//", strval($A[$i]*$B[$j]), -1, PREG_SPLIT_NO_EMPTY);      
            if ($i==0&&$j==0&&count($ZwErg)==2) 
            {
                $l = 1;
            }
            if (count($ZwErg)==2)
            {
                $m = -1;
            }
            for ( $k=0; $k < count($ZwErg); $k++) 
            {
                $s = $i + $j + $l + $m + 1;
                if (isset($Erg[$s])) 
                {
                    $Erg[$s] = intval($Erg[$s]) + intval($ZwErg[$k]);

                    for ( $n=$s; $n >= 0; $n--)
                    {
                        if (intval($Erg[$n])>9) 
                        {
                            $Erg[$n-1] = intval($Erg[$n-1]) + 1 ;
                            $Erg[$n] = intval($Erg[$n] - 10);
                        }
                     };
                }
                else
                {
                    $Erg[$s] = $ZwErg[$k];
                }
                $m = 0;
            }
        }           
    }
    if ($Erg[0]==0) 
    {
        array_splice($Erg,0,1);
    }

    if ($negA*$negB==-1) 
    {
        array_splice($Erg,0,0,"-"); 
    }
    //$Erg = implode("", $Erg);
    return $Erg;
}

.

$time_start = microtime(true);

require'mathlab.php';

$a=array(1,2,3,4,3,1,0,9,5,8,7,6,4,2,5,6,1,2,3,9,5,2,6,7,9,0,4,6,3,9,5,2,6,7,9,0,4,6,7,1,2,3,4,3,1,0,9,5,8,7,6,4,2,5,6,7,8,9,0,3,8,1,5,2,8,1,4,0,7,1,2,3,4,3,1,0,9,5,8,7,6,4,2,5,6,7,8,9,0,3,8,1,5,2,8,1,4,0,3,4,3,1,0,9,5,8,7,6,4,2,5,6,7,8,9,0,7,8,9,0); // 100-digits

$b=array(3,9,5,2,6,7,9,0,4,6,7,1,2,3,4,3,1,0,9,5,8,7,3,9,5,2,6,7,9,3,9,5,2,6,7,9,0,4,6,7,1,2,3,4,3,1,0,9,5,8,7,6,4,2,5,6,7,8,9,0,3,8,1,5,2,8,1,4,0,0,4,6,7,1,2,3,4,3,1,0,9,5,8,7,6,4,2,5,6,7,8,9,0,3,8,1,5,2,8,1,4,0,6,4,2,5,6,7,8,9,0,3,8,1,5,2,8,1,4,0); // 100-digits

$a2=123431095876425612395267904639526790467123431095876425678903815281407123431095876425678903815281403431095876425678907890;

$b2=395267904671234310958739526793952679046712343109587642567890381528140046712343109587642567890381528140642567890381528140;

$d=multiplicate($a, $b);

$time_end = microtime(true);

$time = $time_end - $time_start;

$erg= implode("", $d);

echo $erg;  // returns 48788350638348981414888625840026024706504222587793349182466850334644805413224925671434030836485835140547446449665876539897036829747577622276768694829991017552834308659985345098432904112370002027411248553582029194707890154740774064503024600

echo $time; // returns 0.75173783302307

$erg3=bcmul($a2, $b2);

$erg4=bcmul(123431095876425612395267904639526790467123431095876425678903815281407123431095876425678903815281403431095876425678907890, 395267904671234310958739526793952679046712343109587642567890381528140046712343109587642567890381528140642567890381528140);

$erg2=gmp_mul($a2, $b2);

$erg5=gmp_mul(123431095876425612395267904639526790467123431095876425678903815281407123431095876425678903815281403431095876425678907890, 395267904671234310958739526793952679046712343109587642567890381528140046712343109587642567890381528140642567890381528140);


echo gmp_strval($erg2); // returns 0

echo gmp_strval($erg5); // returns 0

echo $erg3; // returns 0

echo $erg4; // returns 0

【问题讨论】:

  • 如果您真的需要这样的精度,您是否考虑过使用不同的语言?我会说你是在寻找一个大数字库,例如 C# codeproject.com/Articles/2728/C-BigInteger-Class 中的这个,或者查看这篇文章以了解更多不可知论方法 programmers.stackexchange.com/questions/131107/…。 PHP 不太可能是您的最佳选择。
  • 你的 bcmath 有什么问题? 3v4l.org/Ybf1a
  • @Gavin 嗯。无论如何,我这个月想开始学习 java 或 C#,所以是的,我相信我应该选择 C#。但在第二篇文章中,它们甚至不如我 xD 我已经写过 add、sub 和 multi(这里),它们已经在工作了,我只需要一些优化。
  • 我不完全确定您为什么要考虑自己实现这样的功能。严肃的数学天才创造并完善了(在某种程度上)你和我都可以使用的算法,你认为你可以用一两个数组重做他们的工作吗?
  • @RainFromHeaven:我想自己写它的一个原因是我想太了解它,当然也想作为培训。我在哪里可以找到这些完美的算法?正如我已经写过几次的那样,bc math 和 GMP 无法正常工作......而且我找不到该问题的其他工作代码......

标签: php math package largenumber


【解决方案1】:

使用bcmathGMP

例如,

echo bcmul("123431095876425612395267904639526790467123431095876425678903815281407123431095876425678903815281403431095876425678907890",
           "395267904671234310958739526793952679046712343109587642567890381528140046712343109587642567890381528140642567890381528140");

给出输出:

48788350638348981414888625840026024706504222587793349182466850334644805413224925671434030836485835140547446449665876539897036829747577622276768694829991017552834308659985345098432904112370002027411248553582029194707890154740774064503024600

【讨论】:

  • 我不是刚刚写了 bcmath 和 GMP 不是选项。即使这样我很感兴趣为什么它对你有用,但遗憾的是它们对我不起作用,正如我已经写的那样......但我会添加一些更明显的东西......
  • 如果bcmath 在您的系统上不起作用,也许找出原因并修复它会更有成效,而不是自己实现任意精度的数学库。
  • 说得对……但我该如何找出那个问题呢?
猜你喜欢
  • 2011-08-31
  • 2014-03-02
  • 1970-01-01
  • 2010-10-31
  • 1970-01-01
  • 2011-05-26
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
相关资源
最近更新 更多