大整数问题 【微软面试100题 第八十七题】
结构
#define MAXLEN 100 typedef struct HP { int len; int data[MAXLEN]; }HP;
len表示十进制数有多少位,data[0]为符号位,data[1]为个位,data[2]为十位,以此类推。
大整数的加法
#include <stdio.h> #define MAXLEN 100 typedef struct HP { int len; int data[MAXLEN]; }HP; void PrintfHp(const HP x); void Plus(const HP a, const HP b, HP *c); int main(void) { HP a,b,c; a.data[1] = 1;//91 a.data[2] = 9; a.len = 2; b.data[1] = 1;//21 b.data[2] = 2; b.len = 2; Plus(a,b,&c); PrintfHp(c); return 0; } void PrintfHp(const HP x) { int i; for(i = x.len;i > 0;i--) printf("%d",x.data[i]); printf("\n"); } // 大整数的加法 void Plus(const HP a, const HP b, HP *c) { int i; (*c).data[1] = 0; //初始值必须清零 // 大整数a,b的加法操作和结果c的进位操作 for (i=1; i<=a.len || i<=b.len || (*c).data[i]; i++) { if (i <= a.len) (*c).data[i] += a.data[i]; if (i <= b.len) (*c).data[i] += b.data[i]; (*c).data[i+1] = (*c).data[i]/10; //这句话把i+1的值置0或者把进位的值传递 (*c).data[i] %= 10; } // 退出循环到原因是c.s[i]==0,所以取前一位 (*c).len = i-1; if ((*c).len == 0) (*c).len = 1;//对于a和b都为0时,则c应该输出0 }
大整数的减法
#include <stdio.h> #define MAXLEN 100 typedef struct HP { int len; int data[MAXLEN]; }HP; void PrintfHp(const HP x); void Subtract(const HP a, const HP b, HP *c); int main(void) { HP a,b,c; a.data[1] = 3;//33 a.data[2] = 3; a.len = 2; b.data[1] = 5;//25 b.data[2] = 2; b.len = 2; Subtract(a,b,&c); PrintfHp(c); return 0; } void PrintfHp(const HP x) { int i; for(i = x.len;i >= 1;i--) printf("%d",x.data[i]); printf("\n"); } // 大整数的减法 void Subtract(const HP a, const HP b, HP *c) { int i, j =0; for (i=1,j=0; i<=a.len; i++) //说明只能是a>b的情况 { // j表示是否要对高位进行借位 (*c).data[i] = a.data[i] - j; if (i <= b.len) (*c).data[i] -= b.data[i]; if ((*c).data[i] < 0) //这里可以知道结构体HP的data必须是有符号型的 { // 向高位借位,补10 j = 1; (*c).data[i] += 10; } else j = 0; } (*c).len = a.len; //a的位数更多,但是这里面可能首位为0 while ((*c).len > 1 && !(*c).data[(*c).len]) (*c).len--;//这里就是消除高位首位为0的情况。使用>1是因为当全部为0的时候,len=1,为0. }
大整数的乘法
#include <stdio.h> #define MAXLEN 100 typedef struct HP { int len; int s[MAXLEN]; }HP; void PrintfHp(const HP x); void Multi(const HP a, const HP b, HP *c); int main(void) { HP a,b,c; a.s[3] = 9; a.s[2] = 9; a.s[1] = 9; a.s[0] = 0; a.len = 3; b.s[3] = 9; b.s[2] = 9; b.s[1] = 9; b.s[0] = 0; b.len = 3; Multi(a,b,&c); PrintfHp(c); return 0; } void PrintfHp(const HP x) { int i; if(x.s[0] == 1) printf("-"); for(i = x.len;i >= 1;i--) printf("%d",x.s[i]); printf("\n"); } // 大整数的乘法 void Multi(const HP a, const HP b, HP *c) { int i, j; // 对乘法结果赋初值,以方便之后的+=运算 (*c).len = a.len + b.len; for (i=1; i<=(*c).len; i++) (*c).s[i] = 0; for (i=1; i<=a.len; i++) for (j=1; j<=b.len; j++) (*c).s[i+j-1] += a.s[i]*b.s[j]; // 运算结果进位 for (i=1; i<(*c).len; i++) {(*c).s[i+1] += (*c).s[i]/10; (*c).s[i] %= 10;} // 确保最高位不为0 while (i>1 && !(*c).s[i]) i--; (*c).len = i; }
大整数的除法
#include <stdio.h> #define MAXLEN 100 typedef struct HP { int len; int s[MAXLEN]; }HP; void PrintfHp(const HP x); int HPCompare(const HP x, const HP y); void Subtract(const HP a, const HP b, HP *c); void Divide(const HP a, const HP b, HP *c, HP *d); int main(void) { HP a,b,c,d; a.s[3] = 9; a.s[2] = 9; a.s[1] = 9; a.s[0] = 0; a.len = 3; b.s[2] = 2; b.s[1] = 4; b.s[0] = 0; b.len = 2; Divide(a,b,&c,&d); PrintfHp(c); PrintfHp(d); return 0; } void PrintfHp(const HP x) { int i; if(x.s[0] == 1) printf("-"); for(i = x.len;i >= 1;i--) printf("%d",x.s[i]); printf("\n"); } // 大整数的除法 void Divide(const HP a, const HP b, HP *c, HP *d) { int i, j; // 用余数d存被除数a的前i位数据,用来多次减去除数b,以得到商c (*d).len = 1; (*d).s[1] = 0; for (i=a.len; i>0; i--) { if (!((*d).len == 1 && (*d).s[1] == 0)) { // i每移一位,余数d也移位 for (j=(*d).len; j>0; j--) (*d).s[j+1] = (*d).s[j]; (*d).len++; } (*d).s[1] = a.s[i]; (*c).s[i] = 0; // 余数d大于除数b时,才可以进行减操作 while ((j=HPCompare((*d),b)) >= 0) { Subtract((*d), b, d); (*c).s[i]++; if (j == 0) break;// } } (*c).len = a.len; while ((*c).len > 1 && (*c).s[(*c).len] == 0) (*c).len--; } // 大整数的比较 int HPCompare(const HP x, const HP y) { int i; if (x.len > y.len) return 1; if (x.len < y.len) return -1; i = x.len; while (i>1 && (x.s[i]==y.s[i])) i--; return x.s[i] - y.s[i]; } // 大整数的减法 void Subtract(const HP a, const HP b, HP *c) { int i, j; for (i=1,j=0; i<=a.len; i++) { // j表示是否要对高位进行借位 (*c).s[i] = a.s[i] - j; if (i <= b.len) (*c).s[i] -= b.s[i]; if ((*c).s[i] < 0) { // 向高位借位,补10 j = 1; (*c).s[i] += 10; } else j = 0; } (*c).len = a.len; while ((*c).len > 1 && !(*c).s[(*c).len]) (*c).len--; }
带符号的大整数的加减法
/* data[0]作为符号标志位,为1表示为负,为0表示为正。 要这样使用的话,每次使用的时候都要初始化。 代码如下,包含有测试脚手架。 程序主要是在上面不带符号的大整数的加减法的基础上,加上符号修正和大小判断。 */ #include <stdio.h> #define MAXLEN 100 typedef struct HP { int len; int data[MAXLEN]; }HP; void PrintfHp(const HP x); void Subtract(const HP x, const HP y, HP *c); void Plus(const HP x, const HP y, HP *c); int main(void) { HP a,b,c; //测试脚手架------------------------------------------------------ //等位数的情况下的|a| > |b| printf("ab等位数且|a| > |b|:\n"); {//a = 22,b = -21,a+b = 1,a-b = 43 a.data[2] = 2; a.data[1] = 2; a.data[0] = 0; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("%d+(%d) = ",22,-21); PrintfHp(c); c.data[0] = 0; //必须要重新清零 Subtract(a,b,&c); printf("~~~~~~~%d-(%d) = ",22,-21); PrintfHp(c); printf("\n"); } {//a = 22,b = 21,a+b = 43,a-b = 1 a.data[2] = 2; a.data[1] = 2; a.data[0] = 0; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("%d+%d = ",22,21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~%d-%d = ",22,21); PrintfHp(c); printf("\n"); } {//a = -22,b = 21,a+b = -1,a-b = -43 a.data[2] = 2; a.data[1] = 2; a.data[0] = 1; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+%d = ",-22,21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-%d = ",-22,21); PrintfHp(c); printf("\n"); } {//a = -22,b = -21,a+b = -43,a-b = -1 a.data[2] = 2; a.data[1] = 2; a.data[0] = 1; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+(%d) = ",-22,-21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-(%d) = ",-22,-21); PrintfHp(c); printf("\n"); } //等位数的情况下的|a| < |b| printf("\n\nab等位数且|b| > |a|:\n"); {//a = 20,b = -21,a+b = -1,a-b = 41 a.data[2] = 2; a.data[1] = 0; a.data[0] = 0; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("%d+(%d) = ",20,-21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~%d-(%d) = ",20,-21); PrintfHp(c); printf("\n"); } {//a = 20,b = 21,a+b = 41,a-b = -1 a.data[2] = 2; a.data[1] = 0; a.data[0] = 0; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("%d+%d = ",20,21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~%d-%d = ",20,21); PrintfHp(c); printf("\n"); } {//a = -20,b = 21,a+b = 1,a-b = -41 a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+%d = ",-20,21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-%d = ",-20,21); PrintfHp(c); printf("\n"); } {//a = -20,b = -21,a+b = -41,a-b = 1 a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 2; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+(%d) = ",-20,-21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-(%d) = ",-20,-21); PrintfHp(c); printf("\n"); } //a的位数比b的位数大 printf("\n\na的位数比b的位数大:\n"); {//a = -120,b = -21,a+b = -141,a-b = -99 a.data[3] = 1; a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 3; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+(%d) = ",-120,-21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-(%d) = ",-120,-21); PrintfHp(c); printf("\n"); } {//a = 120,b = 21,a+b = 141,a-b = 99 a.data[3] = 1; a.data[2] = 2; a.data[1] = 0; a.data[0] = 0; a.len = 3; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("%d+%d = ",120,21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~%d-%d = ",120,21); PrintfHp(c); printf("\n"); } {//a = -120,b = 21,a+b = -99,a-b = -141 a.data[3] = 1; a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 3; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+%d = ",-120,21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-%d = ",-120,21); PrintfHp(c); printf("\n"); } {//a = -120,b = -21,a+b = -141,a-b = -99 a.data[3] = 1; a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 3; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 2; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+(%d) = ",-120,-21); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-(%d) = ",-120,-21); PrintfHp(c); printf("\n"); } //b的位数比a的位数大 printf("\n\nb的位数比a的位数大:\n"); {//a = -20,b = -121,a+b = -141,a-b = 101 a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 2; b.data[3] = 1; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 3; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+(%d) = ",-20,-121); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-(%d) = ",-20,-121); PrintfHp(c); printf("\n"); {//a = 20,b = 121,a+b = 141,a-b = -101 a.data[2] = 2; a.data[1] = 0; a.data[0] = 0; a.len = 2; b.data[3] = 1; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 3; c.data[0] = 0; Plus(a,b,&c); printf("%d+%d = ",20,121); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~%d-%d = ",20,121); PrintfHp(c); printf("\n"); }} {//a = -20,b = 121,a+b = 101,a-b = -141 a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 2; b.data[3] = 1; b.data[2] = 2; b.data[1] = 1; b.data[0] = 0; b.len = 3; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+%d = ",-20,121); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-%d = ",-20,121); PrintfHp(c); printf("\n"); } {//a = -20,b = -121,a+b = -141,a-b = 101 a.data[2] = 2; a.data[1] = 0; a.data[0] = 1; a.len = 2; b.data[3] = 1; b.data[2] = 2; b.data[1] = 1; b.data[0] = 1; b.len = 3; c.data[0] = 0; Plus(a,b,&c); printf("(%d)+(%d) = ",-20,-121); PrintfHp(c); c.data[0] = 0; Subtract(a,b,&c); printf("~~~~~~~(%d)-(%d) = ",-20,-121); PrintfHp(c); printf("\n"); } //-------------------------------------------------------------------------------- return 0; } void PrintfHp(const HP x) { int i; if(x.data[0] == 1) printf("-"); for(i = x.len;i >= 1;i--) printf("%d",x.data[i]); } // 大整数的减法 void Subtract(const HP x, const HP y, HP *c) { int i, j; HP a = x; HP b = y; //符号修正----------------------------------------------------------- if( (a.data[0] == 0) && (b.data[0] == 1) )//a正b负,则正减负改为正加正 { b.data[0] = 0; Plus(a,b,c); return ; } else if( (a.data[0] == 1) && (b.data[0] == 0) )//a负b正,则改为负的正加正 { a.data[0] = 0; b.data[0] = 0; (*c).data[0] = 1; Plus(a,b,c); return; } else if((a.data[0] == 1) && (b.data[0] == 1) ) { a.data[0] = 0; b.data[0] = 0; Subtract(b,a,c); return; } //else a和b都是正,则直接往下运行即可,不用写 //-------------------------------------------------------------------------- //大小判断------------------------------------------------------------------ if((b.len > a.len)) //位数不等 { (*c).data[0] = 1; Subtract(b,a,c); return ; } else if(a.len == b.len) //位数相等 { i = a.len; while(i >= 1) { if(a.data[i] < b.data[i]) { (*c).data[0] = 1; Subtract(b,a,c); return; } else if(a.data[i] > b.data[i]) break; else if(a.data[i] = b.data[i]) i--; } } //-------------------------------------------------------------------------- for (i=1,j=0; i<=a.len; i++) { // j表示是否要对高位进行借位 (*c).data[i] = a.data[i] - j; if (i <= b.len) (*c).data[i] -= b.data[i]; if ((*c).data[i] < 0) //这里可以知道结构体HP的data必须是有符号型的 { // 向高位借位,补10 j = 1; (*c).data[i] += 10; } else j = 0; } (*c).len = a.len; while ((*c).len > 1 && !(*c).data[(*c).len]) (*c).len--; } // 大整数的加法 void Plus(const HP x, const HP y, HP *c) { int i; HP a = x; HP b = y; //符号判断------------------------------- if((a.data[0] == 1) && (b.data[0] == 1)) (*c).data[0] = 1; else if(a.data[0] == 1) { a.data[0] = 0; Subtract(b,a,c); return; } else if(b.data[0] == 1) { b.data[0] = 0; Subtract(a,b,c); return; } //-------------------------------------- (*c).data[1] = 0; //初始值必须清零 // 大整数a,b的加法操作和结果c的进位操作 for (i=1; i<=a.len || i<=b.len || (*c).data[i]; i++) { if (i <= a.len) (*c).data[i] += a.data[i]; if (i <= b.len) (*c).data[i] += b.data[i]; (*c).data[i+1] = (*c).data[i]/10; //这句话把i+1的值置0或者把进位的值传递 (*c).data[i] %= 10; } // 退出循环到原因是c.s[i]==0,所以取前一位 (*c).len = i-1; if ((*c).len == 0) (*c).len = 1;//对于a和b都为0时,则c应该输出0 }
带符号的大整数的十进制左右移
#include <stdio.h> #define MAXLEN 100 typedef struct HP { int len; int s[MAXLEN]; }HP; void PrintfHp(const HP x); void RightShift(HP *x, int k); void LeftShift(HP *x, int k); int main(void) { HP a; a.s[3] = 6; a.s[2] = 2; a.s[1] = 3; a.s[0] = 1; a.len = 3; RightShift(&a,2); PrintfHp(a); LeftShift(&a,2); PrintfHp(a); return 0; } void PrintfHp(const HP x) { int i; if(x.s[0] == 1) printf("-"); for(i = x.len;i >= 1;i--) printf("%d",x.s[i]); printf("\n"); } // 十进位右移 void RightShift(HP *x, int k) { int i; for (i=1; i<=(*x).len-k; i++) (*x).s[i] = (*x).s[i+k]; (*x).len -= k; if((*x).len <= 0) { (*x).len = 1; (*x).s[1] = 0; } } // 十进位左移 void LeftShift(HP *x, int k) { int i; for (i=(*x).len; i>=1; i--) (*x).s[i+k] = (*x).s[i]; for (i=k; i>=1; i--) (*x).s[i] = 0; (*x).len += k; }
很多时候不是我们做不好,而是没有竭尽全力......
posted on 2014-11-26 20:33 tractorman 阅读(313) 评论(0) 编辑 收藏 举报