大整数问题 【微软面试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编辑  收藏  举报

导航