高精度计算
当对很大的数(比如100位)进行运算时,肯定不能c/c++内的数据类型直接运算(当然Java里的BigNumber可以。。。)这时就要用数组模拟运算过程。+, - ,*, /,运算貌似是小学学的东西,童鞋们,现在要用到小学的知识啦!!
先说加法,大体的操作包括逆序、对位、求和、进位(其实就是小学的加法运算,不过是把数倒过来算,至于为什么要逆序。。。)
例题:http://poj.grids.cn/practice/2981
代码:
#include <stdio.h> #include <string.h> #define MAX 200 int an1[MAX+10]; int an2[MAX+10]; char s1[MAX+10]; char s2[MAX+10]; int main() { scanf("%s", s1); scanf("%s", s2); int i, j; memset( an1, 0, sizeof(an1)); memset( an2, 0, sizeof(an2)); int len1 = strlen( s1); j = 0; for( i = len1 - 1;i >= 0 ; i --) //逆置 an1[j++] = s1[i] - '0'; int len2 = strlen(s2); j = 0; for( i = len2 - 1;i >= 0 ; i --) //逆置 an2[j++] = s2[i] - '0'; len1 = len1 > len2 ? len1 : len2; for( i = 0;i < len1 ; i ++ ) { an1[i] += an2[i]; //求和 if( an1[i] >= 10 ) //进位 { an1[i] -= 10; an1[i+1] ++; } } int flag = 0; for (i = len1 ; i >= 0; i--) //输出 { if (flag || an1[i]) { flag = 1; printf("%d",an1[i]); } } if (!flag) { printf("0"); } printf("\n"); return 0; }
减法同加法类似
例题:http://poj.grids.cn/practice/2736
代码:
#include <stdio.h> #include <string.h> #define MAX 200 int an1[MAX+10]; int an2[MAX+10]; char s1[MAX+10]; char s2[MAX+10]; int main() { int i, j; int n; scanf("%d",&n); while(n--) { scanf("%s", s1); scanf("%s", s2); memset( an1, 0, sizeof(an1)); memset( an2, 0, sizeof(an2)); int len1 = strlen( s1); j = 0; for( i = len1 - 1;i >= 0 ; i --) an1[j++] = s1[i] - '0'; int len2 = strlen(s2); j = 0; for( i = len2 - 1;i >= 0 ; i --) an2[j++] = s2[i] - '0'; for( i = 0;i < len1 ; i ++ ) { an1[i] -= an2[i]; if( an1[i] < 0 ) { an1[i] += 10; an1[i+1] --; } } int flag = 0; for (i = len1 ; i >= 0; i--) { if (flag || an1[i]) { flag = 1; printf("%d",an1[i]); } } if (!flag) { printf("0"); } if(n != 0) printf("\n"); } printf("\n"); return 0; }
乘法同加法类似,不过进位时mod10而不是 -10:
例题:http://poj.grids.cn/practice/2980
代码:
#include <stdio.h> #include <string.h> #define max 200 int an1[max+10]; int an2[max+10]; int result[max*2+10]; char s1[max+10]; char s2[max+10]; int main() { gets(s1); gets(s2); int i, j; memset(an1,0,sizeof(an1)); memset(an2,0,sizeof(an2)); memset(result,0,sizeof(result)); int len1 = strlen(s1); j = 0; for(i = len1-1; i >= 0; i--) an1[j++] = s1[i] - '0'; int len2 = strlen(s2); j = 0; for(i = len2-1; i >= 0; i--) an2[j++] = s2[i] - '0'; for(i = 0; i < len2; i++) for(j = 0; j < len1; j++) result[i+j] += an2[i]*an1[j]; for(i = 0; i < len1*len2; i++) { if(result[i] >= 10) { result[i+1] += result[i]/10; result[i] %= 10; } } int flag = 0; for(i = len1*len2; i >= 0; i--) { if(flag) printf("%d",result[i]); else if(result[i]) { printf("%d",result[i]); flag = 1; } } if(!flag) printf("0"); printf("\n"); return 0; }
除法:
除法可以看作是循环相减,不过在做减法之前有一个判断两数大小的操作;
还是例题:http://poj.grids.cn/practice/2737
代码:
#include <stdio.h> #include <string.h> #define max 200 char s1[max + 10]; char s2[max + 10]; int an1[max + 10]; int an2[max + 10]; int result[max + 10]; int jianfa(int a[], int b[], int len1, int len2) { int i; if(len1 < len2) //----------以下判断大小------------- return -1; int flag = 0; if(len1 == len2) { for(i = len1 - 1; i >= 0; i--) { if(a[i] > b[i]) flag = 1; else if(a[i] < b[i]) { if(!flag) return -1; } } } //-------------以上判断大小------------- for(i = 0; i < len1; i++)//减法 { a[i] -= b[i]; if(a[i] < 0) { a[i] += 10; a[i+1]--; } } for(i = len1 - 1; i >= 0; i--) if(a[i]) return i+1; return 0; } int main() { int i, j, n; scanf("%d",&n); while(n--) { scanf("%s",s1); scanf("%s",s2); memset(an1, 0, sizeof(an1)); memset(an2, 0, sizeof(an2)); memset(result, 0, sizeof(result)); int len1 = strlen(s1); j = 0; for(i = len1 - 1; i >= 0; i--) an1[j++] = s1[i] - '0'; int len2 = strlen(s2); j = 0; for(i = len2 - 1; i >= 0; i--) an2[j++] = s2[i] - '0'; if(len1 < len2) { printf("0\n"); continue; } len1 = jianfa(an1, an2, len1, len2); if(len1 < 0) { printf("0\n"); continue; } else if(len1 == 0) { printf("1\n"); continue; } result[0]++; //减掉一次,商加1 //减去一次后结果的长度是len1 int n = len1 - len2; if(n < 0) //不能再减时 { for(i = 0;i < max; i++) { if(result[i] >= 10) { result[i+1] += result[i]/10; result[i] %= 10; } } } else if(n > 0) { for(i = len1 - 1; i >= 0; i--) { if(i >= n) an2[i] = an2[i-n]; else an2[i] = 0; } } len2 = len1; for(j = 0; j <= n; j++) { int t; while((t = jianfa(an1, an2+j, len1, len2-j)) >= 0) // an2+j 表示把数组的头指针向后移j个位置,即删掉j个an2补上的0 // len2 同时减小j { len1 = t; result[n-j]++; } } for(i = 0;i < max; i++)//进位 { if(result[i] >= 10) { result[i+1] += result[i]/10; result[i] %= 10; } } int flag = 0; for(i = max; i >= 0; i--)//输出 if(flag) printf("%d",result[i]); else if(result[i]) { printf("%d",result[i]); flag = 1; } if(!flag) printf("0\n"); printf("\n"); } return 0; }