您的位置:首页 > 职场人生

大整数问题 【微软面试100题 第八十七题】

2014-11-26 20:33 239 查看

结构

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: