C/C++编程中,过于大的两个数运算会存在溢出的问题,详细了解可看本博客此处。
那怎么运算特别大的数据而不越界溢出呢?以32位机器为例最大的数为0xFFFFFFFF。如果两个数运算如果大于这个数,则会回绕,超出32位的部分被截断,导致实际得到数远远小于想得到的数字。判断溢出的方法在溢出问题中已经详细说明了。
首先是计算一下两个不超出0xFFFFFFFF的值的平均值,面试的时候我的思路是对的,貌似面试官非得往大数运算上引导,这个程序算是开胃菜吧~
#include<stdio.h> #include<limits.h> #include<stdlib.h> int unsigned_num_overflow(unsigned int var_a,unsigned int var_b) { unsigned int result; if(UINT_MAX-var_a < var_b) return 1; else { result=var_a+var_b; printf("%#x\n",result); return 0; } } int main() { unsigned int var_c,var_d; var_c=0xfffffff2; var_d=0xfffffff4; if(unsigned_num_overflow(var_c>>1,var_d>>1)) printf("ungined overflow!!!\n"); }这个程序,利用了溢出判断的条件,两个数都很大但是未超出范围。如果直接相加则可能引起回绕,然后高位被截断,得到的平均数并非为0xfffffff3,而是一个很小的数。这里我想到不相加,先对每个数字进行除以2的处理,这样再加起来必然不会超出范围,按照这个思路给unsigned_num_overflow函数传值是变量的一半,最后计算的结果是正确的0xfffffff3。
那么如果进行相加怎么办呢?而且还要得到正确的结果,这里处理的时候就得使用字符串去处理,具体算法的实现过程,就是两个数以字符串传入,然后从第一个字符开始相加,存入一个整形数组,如果相加大于9,则数组的下一位加1,依次加完所有字符,然后从高到低依次输出所有数据,这个就是最终的需要的数值:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define ARRLEN 10240 void add(char str1[],char str2[]) { int slen1=strlen(str1); int slen2=strlen(str2); int sum1[ARRLEN]={0},sum2[ARRLEN]={0},i=0,j; for(i=slen1-1,j=0;i>=0;i--) sum1[j++]=str1[i]-'0'; for(i=slen2-1,j=0;i>=0;i--) sum2[j++]=str2[i]-'0'; for(j=0;j<ARRLEN;j++) { sum1[j]+=sum2[j]; if(sum1[j]>9) { sum1[j]-=10; sum1[j+1]++; } } for(i=ARRLEN-1;(i>0)&&(sum1[i]==0);i--); if(i>=0) { while(i>=0) { printf("%d",sum1[i]); i--; } } else printf("0\n"); } int main() { printf("please input data:\n"); char data1[ARRLEN],data2[ARRLEN]; scanf("%[^\n]",data1); fflush(stdin); scanf("%[^\n]",data2); add(data1,data2); }