目前在oj上遇到的高精度运算有以下几类
- 高精度整数+高精度整数(poj 2413)
- 高精度整数×普通整数(poj 1001、poj 1306)
- 高精度整数×高精度整数(poj 1405)
- 普通整数÷普通整数(商为高精度浮点数)(poj 1131)
- 高精度数÷普通整数(poj 1220、poj 1306)
高精度整数+高精度整数:
简单。用两个整数数组分别保存加数(a[0]保存最低位),然后逐个元素相加并计算进位。可以一个元素保存一位,也可一个元素保存多位,后者效率更高,但前者能避免输出时的错误。譬如:若一个元素保存三位,则123003004被保存为a[0] = 4, a[1] = 3, a[2] = 123,此时直接输出的结果为12334,明显错误。因此,一个元素保存多位时,记得在输出时补足前导0,具体方法为printf("%0nd", a[i]),表示用0补足n位。示例代码如下:
cf = 0; //cf表示进位
for(int i = 0; i < SIZE; i++){ //一个元素保存一位
c[i] = a[i]+b[i]+cf;
cf = c[i] > 9 ? 1 : 0;
c[i] %= 10;
}
简单。高精度整数仍然用整数数组保存,然后用普通整数与该数组的元素逐个相乘并计算进位。下面的代码仍采用一个元素保存一位的策略:
cf = 0;
for(int i = 0; i < SIZE; i++){
b[i] = a[i]*x+cf; //x为乘数
cf = b[i]/10;
b[i] %= 10;
}
高精度整数×高精度整数:
见另一文章《大数乘法》
普通整数÷普通整数,商为高精度浮点数:
简单。我们采用模拟除法,商的整数部分直接除得,小数部分进行如下循环:将上一次除法所得余数×10,进行除法,获得商的“一位”。示例代码如下:
printf("%d.", a/b); //a为被除数,b为除数
r = a%b;
while(r != 0){ //这里假设能除尽。若除不尽则应设定循环次数,即小数点后的位数,否则会造成无限循环
a = r*10;
printf("%d", a/b);
r = a%b;
}
高精度数÷普通整数:
较难,类似于上面的普通整数÷普通整数求高精度浮点数商。基本思路是:对被除数从高位开始逐位按权累加并与被除数作除法,所得结果为商的某一位,余数计入累加和。若累加和小于被除数,则跳过本次除法使商的该位为0。商可直接原地保存至被除数数组。示例代码如下:
last = 0;
int i;
for(i = size-1; i >= 0; i--){ //a[]为被除数数组,b为除数
cur = last*10+a[i]; //累加和操作
if(cur < b){
a[i] = 0;
last = cur;
}
else{
a[i] = cur/b;
last = cur%b; //余数计入下次累加和
}
}
for(i = size-1; i >= 0; i--) //去除商数组的冗余后缀0
if(a[i] != 0) break;