• 大整数问题 【微软面试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("
    ");
    }
    
    // 大整数的加法
    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("
    ");
    }
    
    // 大整数的减法
    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("
    ");
    }
    // 大整数的乘法
    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("
    ");
    }
    // 大整数的除法
    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|:
    ");
    {//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("
    ");
    }
    {//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("
    ");
    }
    {//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("
    ");
    }
    {//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("
    ");
    }
    //等位数的情况下的|a| < |b|
        printf("
    
    ab等位数且|b| > |a|:
    ");
    {//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("
    ");
    }
    {//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("
    ");
    }
    {//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("
    ");
    }
    {//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("
    ");
    }
    //a的位数比b的位数大
        printf("
    
    a的位数比b的位数大:
    ");
    {//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("
    ");
    }
    {//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("
    ");
    }
    {//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("
    ");
    }
    {//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("
    ");
    }
    //b的位数比a的位数大
        printf("
    
    b的位数比a的位数大:
    ");
    {//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("
    ");
    
    {//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("
    ");
    }}
    {//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("
    ");
    }
    {//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("
    ");
    }
    //--------------------------------------------------------------------------------
        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("
    ");
    }
    // 十进位右移
    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;
    }
  • 相关阅读:
    加入mapstruct后出现 找不到符号 符号: 方法 setXX 的解决方法
    解决docker容器日志导致主机磁盘空间满了的情况
    prometheus安装(docker)
    在Github或Gitee上用hexo搭建个人博客
    解决github打不开
    jenkins更新为国内源
    让sentinel-dashboard的流控配置持久化到nacos
    Yarn和Zookeeper的区别
    flink安装启动(docker)
    jQuery 事件源码定位
  • 原文地址:https://www.cnblogs.com/tractorman/p/4124858.html
Copyright © 2020-2023  润新知