<?php
function makeSameLen(&$num1, &$num2){
$len1 = strlen($num1);
$len2 = strlen($num2);
if($len1 < $len2){
for($i = 0; $i < $len2 - $len1; $i++){
$num1 = '0'.$num1;
}
return $len2;
}else if($len1 > $len2){
for($i = 0; $i < $len1 - $len2; $i++){
$num2 = '0'.$num2;
}
return $len1;
}else{
return $len1;
}
}
function minusString($num1, $num2) {
$result = [];
$len1 = strlen($num1);
$len2 = strlen($num2);
if($num1 == $num2){
return '0';
}
$positive = true;
if($len1 < $len2 || ($len1 == $len2 && $num1 < $num2)){
$positive = false;
//交换使 num1 > num2
$tmp = $num1;
$num1 = $num2;
$num2 = $tmp;
$temp = $len1;
$len1 = $len2;
$len2 = $temp;
}
$i = $len1 - 1;
$j = $len2 - 1;
$carray = 0;
//从低位到高位对位做减法
while($i >= 0 || $j >= 0){
$a = $i >= 0 ? $num1[$i] : 0;
$b = $j >= 0 ? $num2[$j] : 0;
$sum = $a - $b + $carray;
$carray = 0;
//不够减
if($sum < 0){
$sum += 10;
$carray = -1;
}
$result[] = $sum;
$i--;
$j--;
}
//删除前导0
$result = array_reverse($result);
$result = implode('', $result);
$result = ltrim($result, 0);
$result = $positive ? $result : '-'.$result;
return strval($result);
}
function addString($num1, $num2){
$result = [];
$len1 = strlen($num1);
$len2 = strlen($num2);
if($len1 == 0){
return $num2;
}
if($len2 == 0){
return $num1;
}
$i = $len1 - 1;
$j = $len2 - 1;
$carry = 0;
//倒序相加
while($i >= 0 || $j >= 0 || $carry > 0){
$a = $i >= 0 ? $num1[$i] : 0;
$b = $j >= 0 ? $num2[$j] : 0;
//按位相加并加上进位
$sum = $a + $b + $carry;
//进位
$carry = intval($sum / 10);
$result[] = $sum % 10;
$i--;
$j--;
}
$result = array_reverse($result);
$result = implode('', $result);
return strval($result);
}
//左移
function shiftString($num, $len){
if($num == '0'){
return $num;
}
for($i = 0; $i < $len; $i++){
$num .= '0';
}
return strval($num);
}
//Karatsuba快速相乘算法
function karatsubaMultiply($num1, $num2){
$len = MakeSameLen($num1,$num2);
if($len == 0){
return 0;
}
if($len == 1){
return strval($num1[0] * $num2[0]);
}
$mid = intval($len / 2);
$m = $len - $mid;
$x1 = substr($num1,0, $mid);
$x0 = substr($num1, $mid, $m);
$y1 = substr($num2,0, $mid);
$y0 = substr($num2,$mid, $m);
$z0 = karatsubaMultiply($x0, $y0);
$z1 = karatsubaMultiply(addString($x1, $x0), addString($y1, $y0));
$z2 = karatsubaMultiply($x1, $y1);
// (z2*10^(2*m))+((z1-z2-z0)*10^(m))+(z0)
// z2*10^(2*m)
$r1 = shiftString($z2,2 * $m);
// (z1-z2-z0)*10^(m)
$z1MinusZ2 = minusString($z1, $z2);
$z1MinusZ2MinusZ0 = minusString($z1MinusZ2, $z0);
$r2 = shiftString($z1MinusZ2MinusZ0, $m);
$result = addString(addString($r1, $r2), $z0);
return strval($result);
}
$num1 = '123';
$num2 = '5678';
$result = karatsubaMultiply($num1, $num2);
echo $num1.' * '.$num2.' = '.$result.PHP_EOL;
Karatsuba乘法
转载huang_he_87 博主文章分类:《算法的乐趣》
文章标签 Karatsuba乘法 文章分类 后端开发
-
大数乘法
51Nod 10271027 大数乘法 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
大数乘法 数组 #include -
2.c++面向对象(三)
插播补充知识:在类里面,不声明默认是内联函数,但是声明和定义分离就不是内联函数了。
#c++ #开发语言 赋值 d3 运算符重载
















