高精度算法
¶高精度问题
高精度主要是解决处理大整数时的问题,这里的整数范围要超过longlong。
高精度问题的核心就是使用字符串去模拟加法、减法、乘法、除法运算
¶高精度加法
¶基本
使用三个数组a[],b[],c[]
存储
模拟加法竖式:累加 进位 留位
-
累加:
c[i] += a[i] + b[i]
——>必须要累加之前的进位,使用 += //累加进位和对应位置的数字 -
进位:
c[i+1] = c[i] / 10;
-
留位:
c[i] %= 10;
Q1:假设正整数A的长度为n,正整数B的长度为m,那么A+B的长度最大为多少?最小为多少?
- A1: 长度最大:
max(n,m)+1
长度最小:max(n,m)
¶算法步骤
- 高精度数的读取与存储:使用字符串方式读取,然后将每一个字符转为整数,逆向存储到一个整型数组中
- 模拟加法操作:通过数组下标模拟两个加数中每一个为上数的加法(累加、进位、留位)
- 去除前导0,逆向重组(因为之前是逆向加,再反过来)
¶高精度加法函数
1 | // a,b数组用于存储A,B两个加数,c数组用于存储相加之和 |
¶高精度减法
¶基本
- 如果
a[i] < b[i]
:说明a[i] 需要向a[i+1]借位:1
2a[i+1]--;
a[i]+=10; - 模拟减法:
c[i] = a[i] - b[i];
- 高精度减法的程序计算中都默认a 是大于 b来计算的,如果实际情况是a < b,那么只需要交换一下a,b即可
- 下面提到的a、as都是指减法运算中较大的那一个(被减数),b、bs同理都是值减数
Q1: 如果a[i+1] == 0,这样借位会不会有问题
- A1: 不会,因为最多只会借一位。a[i+1]被借位后等于-1,因为a>b(在模拟计算的算法中都转化为a>b来计算,后文详解),a[i+1]还可以向a[i+2]借位。借位后a[i+1] == 9,而b[i+1]最大也才为9。
¶算法步骤
- 高精度数的读取与存储:使用字符串方式读取,然后将每一个字符转为整数,逆向存储到一个整型数组中
- 模拟减法计算:相同位置进行相减,不够减时向高位借位
- 去除前导0,再逆序输出
Q1:两个长整数a,b,并且a>b,长度分别为n,m,那么c = a-b的长度最长为多少?
- A1:n
Q2:两个正整数字符串as,bs,如何判断as和bs的大小(也即a和b的大小)?
- A2 :
if( as.size() < bs.size() || (as.size() == bs.size() && as < bs))
成立,那么说明as < bs ---> 长整数a < b
Q3:如果a<b,如何计算a-b的值呢?
- A3: 交换a和b的值,然后计算a-b,结果输出一个负号
¶计算高精度减法函数
1 | int a[200+10],b[200+10],c[200+10]; |
¶高精度乘法
¶基本
- 本质上还是使用字符串来模拟整数的乘法计算过程
$\qquad\qquad\qquad b_3 \qquad\qquad\qquad b_2 \qquad\qquad\qquad b_1$
$\times\qquad\qquad\qquad\qquad\qquad\qquad a_2 \qquad\qquad\qquad a_1$
$—————————————————————————$
$\qquad\qquad\qquad b_3\ast a_1 \qquad\qquad b_2\ast a_1 \qquad\qquad b_1\ast a_1$
$\quad b_3\ast a_1 \qquad b_2\ast a_1 \qquad\qquad b_1\ast a_1$
$—————————————————————————$
$\qquad c_4 \quad\quad\qquad c_3 \qquad\qquad\qquad c_2 \qquad\qquad\qquad c_1$
- 观察式子的下标可以发现
c[i+j-1] += a[i]*b[j]
高精度乘法算式的模拟
- 下面的模拟是按照乘法结果的每一行来模拟的,即先把 $a_1$ 与b相乘的加到c中去,再把 $a_2$ 与b相乘的加到c中去
1 | for(int i=1;i<=alen;i++){ |
Q1:设整数A的长度为n,整数B的长度为m,那么A*B的长度最大为多少,最小为多少
- A1: A*B的长度最长不会超过n+m,最短不会低于max(n,m)
¶算法步骤
时间复杂度O(n*m)
- 高精度数的读取与存储:使用字符串方式读取,然后将每一个字符转为整数,逆向存储到一个整型数组中
- 模拟乘法计算
- 去除前导0
- 逆序重组
¶高精度乘法函数
1 | const int N = 210; |
¶高精度除法(长数/短数)
这里的高精度除法指的是一个长数(被除数)和一个短数(除数)做高精度除法
¶基本
- 将长数做字符串处理转为整数存入数组,但与高精度加减法和乘法不同,除法的长数不需要做逆向存储
- 模拟的过程是从长数的高位开始与除法进行除法与取模
1
2
3
4
5
6int r=0;
for(int i=1;i<=clen;i++){
r = r*10 + a[i]; //构造被除数,依次称10进位
c[i] = r/x; //得到商
r %= x; //除剩的余数再进入到下一轮除法
}
Q1:设长整数A的长度为n,短整数B的长度为m,那么A/B的长度最大为多少,最小为多少
- A1: A/B的长度最长不会超过n,最短为1
¶算法步骤
- 高精度数的读取与存储:使用字符串方式读取,然后将每一个字符转为整数,正向存储到一个整型数组中
- 从高位开始进行模拟除法计算
- 去除前导0
- 正序重组
¶高精度除法函数
1 | const int N =10000+10; |
¶求余数
同求商类似,最后只需要返回r即可
1 | const int N =10000+10; |