大整数的加减乘运算
在做CODE[VS]的天梯时遇到的三道题目,在平时也是有一定的用处的,便整理出来发表一下:
先从减法开始,对于减法,我觉得唯一需要考虑的点就是在一开始有必要比较两个字符串并将负号有必要的话打印出来,然后将其转化为一个较大的数减较小的数的过程,为了方便运算,直接多定义三个整数数组来储存字符串对应位的数字.然后进行运算,如果减数小于零的话,向高位借位.
再考虑一下加法,加法甚至可以不需要再多定义数组了,我们可以直接从低位向高位加,大于等于10就进位,最后得出的字符串反向输出.
最后比较麻烦的乘法,乘法其实有种时间复杂度为O(nlogn)的FFT算法,但是用到数论的知识仍未参透,所以这里我们还是考虑用双重循环来构造一个时间复杂度的O(n^2)的算法,我们首先需要研究一下乘法这个运算,如果稍作研究我们就可以得出来最后得出的结果是这么计算得到的:以1234*6789为例:
根据这张表我们可以得出运算的方法,依次来写程序.这里用一个结构体数组,也是想到可以用这个顺便来记录字符串长度,我们没有必要去打一个二维数组,这样有点浪费空间,我们发现,其实每个位对应的只是二维矩阵的2*n - 1条对角线而已,所以只要在循环的时候叠加即可.然后进行对数组中的数进行除以10赋值和余10进位.最后我们只要讨论一下最高位是不是0然后输出的时候稍作更改即可.
下面是代码:
/************************************************************************* > File Name: 高精度练习.cpp > Author: zhanghaoran > Mail: chilumanxi@gmail.com > Created Time: 2015年06月17日 星期三 12时46分56秒 ************************************************************************/ #include <iostream> #include <algorithm> #include <utility> #include <cstring> #include <cstdio> using namespace std; char s1[501]; char s2[501]; char s3[501]; int t1[501]; int t2[501]; int t3[501]; struct node{ int num[1010]; int l; }; node a, b, c; char s[1010]; int max(int a, int b){ return a > b ? a : b; } int solve_plus(void){ cin >> s1; cin >> s2; memset(t1, 0, sizeof(t1)); memset(t2, 0, sizeof(t2)); memset(t3, 0, sizeof(t3)); int n1 = strlen(s1) - 1; int n2 = strlen(s2) - 1; if(n1 < n2 || (n1 == n2 && strcmp(s1, s2) < 0)){ strcpy(s3, s1); strcpy(s1, s2); strcpy(s2, s3); cout << '-'; } n1 = strlen(s1) - 1; n2 = strlen(s2) - 1; for(int i = 0; i <= n1; i ++){ t1[i] = s1[n1 - i] - '0'; } for(int i = 0; i <= n2; i ++){ t2[i] = s2[n2 - i] - '0'; } for(int i = 0; i <= n1; i ++){ t3[i] = t1[i] - t2[i]; if(t3[i] < 0){ t3[i] += 10; t1[i + 1] --; } } while(t3[n1] == 0 && n1 > 0) n1 --; for(int i = n1; i >= 0; i --) cout << t3[i]; return 0; } int solve_add(void){ cin >> s1; cin >> s2; int n1 = strlen(s1) - 1; int n2 = strlen(s2) - 1; int ans = 0; for(int i = 0; i < max(n1, n2) + 1; i ++) s3[i] = '0'; while(n1 >= 0 && n2 >= 0){ if(s1[n1] - 48 + s2[n2] - 48 > 10){ s3[ans] = s1[n1] + s2[n2] - 96 - 10; s3[ans + 1] += 1; } else (s3[ans] = s1[n1] - 48 + s2[n2] - 48); n1 --; n2 --; ans ++; } if(n1 >= 0){ for(int i = n1; i >= 0; i --){ if(s3[ans] + s1[i] - 48 > 10){ s3[ans] = s1[i] - 48 - 10; s3[ans + 1] += 1; } else{ s3[ans] += s1[i] - 48; } ans ++; } } else{ for(int i = n2; i >= 0; i --){ if(s3[ans] + s2[i] - 48 > 10){ s3[ans] = s2[i] - 48 - 10; s3[ans + 1] += 1; } else{ s3[ans] += s2[i] - 48; } ans ++; } } for(int i = ans - 1; i >= 0; i --) printf("%d", s3[i]); return 0; } void solve_multiply(){ memset(a.num, 0, sizeof(a.num)); memset(b.num, 0, sizeof(b.num)); memset(c.num, 0, sizeof(c.num)); cin >> s; a.l = strlen(s); for(int i = 0; i < a.l; i ++){ a.num[a.l - 1 - i] = s[i] - '0'; } cin >> s; b.l = strlen(s); for(int i = 0; i < b.l; i ++){ b.num[b.l - 1 - i] = s[i] - '0'; } c.l = a.l + b.l; for(int i = 0; i < a.l; i ++){ for(int j = 0; j < b.l; j ++){ c.num[i + j] += a.num[i] * b.num[j]; } } for(int i = 0; i < c.l; i ++){ if(c.num[i] > 9){ c.num[i + 1] += c.num[i] / 10; c.num[i] = c.num[i] % 10; } } while(c.l > 1 && c.num[c.l - 1] == 0) c.l --; for(int i = c.l - 1; i >= 0; i --) cout << c.num[i]; }
当然这只是大整数处理的入门,其他深入的算法以后慢慢讨论.