- 分享
高精度算法——高精度乘法
- 2022-9-7 20:52:01 @
高精度乘法,会比高精加法、减法稍微难那么一点点,主要是乘法要用到,高精度加法去做,也就是说,如果高精度加法没有学好,高精度乘法也就会有点难理解了,但是吧,你既然点到了这里,就说明你已经会高精度加法了,既然你已经会高精度加法了,就说明你知道为什么要用高精度了,就不再多说废话了。
c/c++
最大也就是unsigned long long
也就才位
如果要几百位的相乘除就不行了,所以就要用高精度了,但高精度是什么呢,一句话,就是处理很大的数相加减之类就比如几百位的数乘,就是很大的数。
高精度——单精度
高精度乘法,也就是竖……………………等会儿等会儿!
先考虑一个简单的情况:乘数中的一个是普通的 int 类型。有没有简单的处理方法呢? 一个直观的思路是直接将a每一位上的数字乘以b。从数值上来说,这个方法是正确的,但它并不符合十进制表示法,因此需要将它重新整理成正常的样子。 重整的方式,也是从个位开始逐位向上处理进位。但是这里的进位可能非常大,甚至远大于 9,因为每一位被乘上之后都可能达到 9b 的数量级。所以这里的进位不能再简单地进行 -10 运算,而是要通过除以 10 的商以及余数计算。详见代码注释,也可以参考下图展示的一个计算高精度数 1337 乘以单精度数 42 的过程。
当然,也是出于这个原因,这个方法需要特别关注乘数的范围。若它和(或相应整型的取值上界)属于同一数量级,那么需要慎用高精度—单精度乘法。
最终算法:
(算法不懂的请看注释)
void mul_short(int a[], int b, int c[]) {
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
// 直接把 a 的第 i 位数码乘以乘数,加入结果
c[i] += a[i] * b;
if (c[i] >= 10) {
// 处理进位
// c[i] / 10 即除法的商数成为进位的增量值
c[i + 1] += c[i] / 10;
// 而 c[i] % 10 即除法的余数成为在当前位留下的值
c[i] %= 10;
}
}
}
高精度——高精度
如果两个乘数都是高精度,那么竖式乘法又可以大显身手了。
回想竖式乘法的每一步,实际上是计算了若干 的和。例如计算 ,计算的就是 $1337 \times 2 \times 10^0 + 1337 \times 4 \times 10^1$。 于是可以将b分解为它的所有数码,其中每个数码都是单精度数,将它们分别与a相乘,再向左移动到各自的位置上相加即得答案。当然,最后也需要用与上例相同的方式处理进位。
注意这个过程与竖式乘法不尽相同,我们的算法在每一步乘的过程中并不进位,而是将所有的结果保留在对应的位置上,到最后再统一处理进位,但这不会影响结果。
最终算法:
(算法不懂的请看注释)
void mul(int a[], int b[], int c[]) {
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
// 这里直接计算结果中的从低到高第 i 位,且一并处理了进位
// 第 i 次循环为 c[i] 加上了所有满足 p + q = i 的 a[p] 与 b[q] 的乘积之和
// 这样做的效果和直接进行上图的运算最后求和是一样的,只是更加简短的一种实现方式
for (int j = 0; j <= i; ++j) c[i] += a[j] * b[i - j];
if (c[i] >= 10) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
}
}
算法都教了,怎能不上食用方法呢?
食用方法:
#include<iostream>
#include<string>
using namespace std;
const int N = 100000000;
int a[N], b[N], c[N];
int main()
{
string str1;
string str2;
//以上是定义
cin >> str1 >> str2;//输入
for (int i = 0; i < str1.size(); i ++)//输入
a[str1.size()-1-i] = str1[i] - '0';
for (int i = 0; i < str2.size(); i ++)//输入
b[str2.size()-1-i] = str2[i] - '0';
for (int i = 0; i < str1.size(); i ++){ //最终算法的运算
for (int j = 0; j < str2.size(); j ++){
c[j+i] += a[i] * b[j];
c[j+1+i] += c[j+i] / 10;
c[j+i] %= 10;
}
}int as = str1.size() + str2.size();
while (c[as-1] == 0 && as > 1)//下面是输出
as -= 1;
for (int i = 0; i < as; i ++)
cout << c[as-1-i];
return 0;
}
0 条评论
目前还没有评论...