如何在PHP中打印正确的大数乘法

如何在PHP中打印正确的大数乘法,php,Php,我试着打印大数字的乘法,结果是浮点数 var_dump((double)('290287121823'*'290287121823')); 我尝试使用函数number_format和preg_replace删除所有','。但是在数字_格式之后,结果是不正确的 使用以下代码: preg_replace("/,/", "", (number_format(('290287121823'*'290287121823')))); 收到的输出:8426661309621242861568 预期正确输出

我试着打印大数字的乘法,结果是浮点数

var_dump((double)('290287121823'*'290287121823'));
我尝试使用函数number_format和preg_replace删除所有','。但是在数字_格式之后,结果是不正确的

使用以下代码:

preg_replace("/,/", "", (number_format(('290287121823'*'290287121823'))));
收到的输出:8426661309621242861568

预期正确输出:8426661309621243382112


大数字是逐位计算的。就像我们在学校学习一样(见)

例:

这里有一个函数(应该优化),但向您展示了原理

echo bn_mul('17', '27'), PHP_EOL; // 459
echo bn_mul('157', '27'), PHP_EOL; // 4239
echo bn_mul('1234', '6627'), PHP_EOL; // 8177718
echo bn_mul('23958233', '5830'), PHP_EOL; // 139676498390
echo bn_mul('290287121823', '290287121823'), PHP_EOL; // 84266613096281242843329
实施:

function bn_mul($n2, $n1) {

    $l1 = strlen($n1);
    $l2 = strlen($n2);

    $rows = [];

    for ($idx1 = $l1 - 1 ; $idx1 >= 0 ; $idx1--) {
        // get digit
        $d1 = substr($n1, $idx1, 1) ;

        $carry = 0; // reset carry
        $row = []; // store digit of $d1 x each digits of $n2

        // prepend 0 (10 * num rows)
        for ($x=0 ; $x<count($rows) ; $x++) $row[] = 0;

        for ($idx2 = $l2 - 1 ; $idx2 >= 0 ; $idx2--) {

            // get digit
            $d2 = substr($n2, $idx2, 1) ;
            // multiplication of digit 1 x digit 2 + current carry
            $r = $d1 * $d2 + $carry;

            $carry = 0;

            // compute carry
            if ($r >= 10) {
                $carry = substr($r, 0, -1);
                $r = substr($r, -1);
            }
            $row[] = $r ;
        }

        if ($carry) $row[] = $carry;

        $rows[] = $row ;
    }


    // Sum digits of rows
    $total = [] ;
    $carry = 0 ;
    for ($x=0;$x < count(end($rows)) ; $x++){
        $tot = $carry;
        $carry = 0;
        foreach ($rows as $row){
            if (isset($row[$x])) $tot += $row[$x] ;
        }
        while ($tot >= 10) {
            $tot -= 10;
            $carry++;
        }
        $total[$x] = $tot;
    }

    return strrev(implode($total));
}
函数bn_mul($n2,$n1){
$l1=strlen($n1);
$l2=strlen($n2);
$rows=[];
对于($idx1=$l1-1;$idx1>=0;$idx1--){
//获取数字
$d1=substr($n1,$idx1,1);
$carry=0;//重置进位
$row=[];//存储$d1的数字x$n2的每个数字
//前置0(10*num行)
对于($x=0;$x=0;$idx2--){
//获取数字
$d2=substr($n2,$idx2,1);
//数字1乘以数字2+当前进位
$r=$d1*$d2+$carry;
$carry=0;
//计算进位
如果($r>=10){
$carry=substr($r,0,-1);
$r=子项($r,-1);
}
$row[]=$r;
}
如果($carry)$row[]=$carry;
$rows[]=$row;
}
//行数总和
$total=[];
$carry=0;
对于($x=0;$x=10){
$tot-=10;
$carry++;
}
$total[$x]=$tot;
}
返回strrev(内爆($total));
}

您应该记住,即使PHP不是类型安全的,后台也有类型

当你查找时,你会发现,浮点的精度只有14位。因此,所有尾随数字都被“截断”。震级仍然存在,它将以科学的格式打印出来,但你无法真正知道“低于”14位的是什么。因此,您试图转换结果的尝试首先注定要失败

例如:

12345678910111213
              ^^^ get's cut off

如果你需要大于64位的整数,你应该看看我们可以不使用GMP或BC数学来计算吗?你如何计算你的结果?这个乘法的结果是
8426661309621242843329
,对吗?最后两位数字是3,因此最终结果的最后一位数字是9。
12345678910111213
              ^^^ get's cut off