如何在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