传说中大数据处理的那些事曾是那样的困扰我们。
往往是我们的面试杀手。
其实面对大数据的运算就是划分,根据庖丁解牛的原理:
方法有很多。但是最常用的是用数组和链表存储每一位数据。这两种方法各有优略。
下面给大家讲述一种:数组的实现:
大数据用一个int类型的数组存放,为了处理方便(其实char数组也可以),数组最高位存放大数据的长度
加法:
int bigplus(int a[],int b[],int c[]) //大整数加法 { int i,len; len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个 for(i=0;i<MAXINT;i++) //将数组清0 c[i]=0; for (i=1;i<=len;i++) //计算每一位的值 { c[i]+=(a[i]+b[i]); if (c[i]>=10) { c[i]-=10; //大于10的取个位 c[i+1]++; //高位加1 } } if (c[i+1]>0) len++; c[0]=len; //c[0]保存结果数组实际长度 printf("Big integers add: "); for (i=len;i>=1;i--) printf("%d",c[i]); //打印结果 printf(" "); return 0; }
代码很清楚,不需要过多解释,注释也很详细,主要是分开处理
另外:对于结果高位处理的地方和下面乘除不一样。因为两个数相加,最高位最多只进位一位,所以,没有while循环处理,只有if语句判断处理即可
和加法相似的就是乘法,先看代码:
乘法1:一个大数据和一个范围内的数据相乘
int bigmult(int a[],unsigned int b,int c[])//高精度乘以低精度 { int len,i; for (i=0;i<MAXINT;i++) //数组清0 c[i]=0; len=a[0]; for(i=1;i<=len;i++) //对每一位计算 { c[i]+=a[i]*b; c[i+1]+=c[i]/10; c[i]%=10; } while (c[++len]>=10) //处理高位 { c[len+1]=c[len]/10; c[len]%=10; } if (c[len]==0) len--; //处理高进位为0情况 printf("Big integrs multi small integer: "); for (i=len;i>=1;i--) printf("%d",c[i]); printf(" "); return 0; }
乘法2:两个大数据相乘:
int bigmult2(int a[],int b[],int c[]) //高精度乘以高精度 { int i,j,len; for (i=0;i<MAXINT;i++) //数组清0 c[i]=0; for (i=1;i<=a[0];i++) //被乘数循环 for (j=1;j<=b[0];j++) //乘数循环 { c[i+j-1]+=a[i]*b[j]; //将每一位计算累加 c[i+j]+=c[i+j-1]/10; //将每一次结果累加到高一位 c[i+j-1]%=10; //计算每一次的个位 } len=a[0]+b[0]; //取最大长度 while (len>1 && c[len]==0) //去掉高位0 len--; c[0]=len; printf("Big integers multi: "); for (i=len;i>=1;i--) //打印结果 printf("%d",c[i]); printf(" "); return 0; }
其实对于乘法来说,就是相对复杂一点的加法。两个实现原理是一样的
最后的高位处理是因为,两个数据相乘时并不确定结果多少位,只能尽可能多的给空间,然后再处理高位,算出最终真正有效的程度
在处理减法和除法的时候要用到比较,因此先给出比较函数:
int compare(int a[],int b[]) //比较大整数的大小 { int i; if (a[0]>b[0]) return 1; //比较a,b的位数确定返回值 else if(a[0]<b[0]) return -1; else //位数相等时的比较 { i=a[0]; while (a[i]==b[i]) //逐位比较 i--; if (i==0) return 0; else if(a[i]>b[i]) return 1; else return -1; } }
然后我们看减法的实现:
减法:
int bigsub(int a[],int b[],int c[]) //大整数减法 { int i,len; len=(a[0]>b[0]?a[0]:b[0]); //a[0]保存数字长度,len为较长的一个 for(i=0;i<MAXINT;i++) //将数组清0 c[i]=0; if (compare(a,b)==0) //比较a,b大小 { printf("Result:0"); return 0; } else if(compare(a,b)>0) { for (i=1;i<=len;i++) //计算每一位的值 { c[i]+=(a[i]-b[i]); if (c[i]<0) { c[i]+=10; //小于0的原位加10 c[i+1]--; //高位减1 } } } else { for (i=1;i<=len;i++) //计算每一位的值 { c[i]+=(b[i]-a[i]); if (c[i]<0) { c[i]+=10; //小于0原位加10 c[i+1]--; //高位减1 } } } while (len>1 && c[len]==0) //去掉高位的0 len--; c[0]=len; printf("Big integers sub= "); if (a[0]<b[0]) printf("-"); for(i=len;i>=1;i--) //打印结果 printf("%d",c[i]); printf(" "); return 0; }
加法,分情况处理,其实代码可以简化,但是这样便于理解
除法1:大数据除以一个范围内的数据
int bigdiv(int a[],unsigned int b,int c[],int *d) //高精度除以低精度 { //a[] 为被乘数,b为除数,c[]为结果,d为余数 int i,len; len=a[0]; //len为a[0]的数组长度 for (i=len;i>=1;i--) { (*d)=10*(*d)+a[i]; //计算每一步余数 c[i]=(*d)/b; //计算每一步结果 (*d)=(*d)%b; //求模余数 } while (len>1 && c[len]==0) //去高位0 len--; printf("Big integer div small integer: "); for (i=len;i>=1;i--) //打印结果 printf("%d",c[i]); printf(" Arithmetic compliment:%d",*d); printf(" "); return 0; }
除法2: 大数据处以大数据
int bigdiv2(int a[],int b[],int c[],int d[]) //高精度除以高精度 { int i,j,len; if (compare(a,b)<0) //被除数较小直接打印结果 { printf("Result:0"); printf("Arithmetic compliment:"); for (i=a[0];i>=1;i--) printf("%d",a[i]); printf(" "); return -1; } for (i=0;i<MAXINT;i++) //商和余数清0 { c[i]=0; d[i]=0; } len=a[0];d[0]=0; for (i=len;i>=1;i--) //逐位相除 { for (j=d[0];j>=1;j--) d[j+1]=d[j]; d[1]=a[i]; //高位*10+各位 d[0]++; //数组d长度增1 while (compare(d,b)>=0) //比较d,b大小 { for (j=1;j<=d[0];j++) //做减法d-b { d[j]-=b[j]; if (d[j]<0) { d[j]+=10; d[j+1]--; } } while (j>0 && d[j]==0) //去掉高位0 j--; d[0]=j; c[i]++; //商所在位值加1 } } j=b[0]; while (c[j]==0 && j>0) j--; //求商数组c长度 c[0]=j; printf("Big integers div result: "); for (i=c[0];i>=1;i--) //打印商 printf("%d",c[i]); printf(" Arithmetic compliment: "); //打印余数 for (i=d[0];i>=1;i--) printf("%d",d[i]); printf(" "); return 0; }
除法的原理就是从高位到地位,利用余数作为过渡,一位一位的除,不够的补0,然后继续向地位平移。
下面的是上面的复杂版,原理是一样的。其实看代码理解起来并不难