如何在PHP

时间:2018-04-04 05:59:00

标签: php

我试图打印大数字的乘法,它们导致浮点型科学数字。

var_dump((double)('290287121823'*'290287121823'));

我尝试使用函数number_format和preg_replace删除所有','。但是在number_format之后,结果不正确。

使用以下代码:

preg_replace("/,/", "", (number_format(('290287121823'*'290287121823'))));
  

收到的产出:84266613096281242861568

     

预期正确输出:84266613096281243382112

2 个答案:

答案 0 :(得分:0)

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

例如:

//    17
//  x 27
//  ----
//   119
// + 34 
// -----
// = 459

这是一个功能(应该进行优化),但会向您展示原理。

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));
}

答案 1 :(得分:0)

你应该记住,即使PHP不是类型安全的,背景中也有类型。

当您查找documentation时,您会发现,浮动点的精度最高可达14位。因此,所有尾随数字都被“切断”。幅度仍然存在,并且将以科学格式打印,但您无法真正知道14位数字的“低于”。因此,您尝试转换结果注定首先失败。

示例:

12345678910111213
              ^^^ get's cut off