zoukankan      html  css  js  c++  java
  • 高精度运算

    首先一个别人总结的模版,我觉得很好就引用一下

    /**高精度模版*/
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    using  namespace  std;
    
    const  int MAXL = 500;
    struct  BigNum
    {
        int  num[MAXL];
        int  len;
    };
    
    //高精度比较 a > b return 1, a == b return 0; a < b return -1;
    int  Comp(BigNum &a, BigNum &b)
    {
        int  i;
        if(a.len != b.len) return (a.len > b.len) ? 1 : -1;
        for(i = a.len-1; i >= 0; i--)
            if(a.num[i] != b.num[i]) return  (a.num[i] > b.num[i]) ? 1 : -1;
        return  0;
    }
    
    //高精度加法
    BigNum  Add(BigNum &a, BigNum &b)
    {
        BigNum c;
        int  i, len;
        len = (a.len > b.len) ? a.len : b.len;
        memset(c.num, 0, sizeof(c.num));
        for(i = 0; i < len; i++)
        {
            c.num[i] += (a.num[i]+b.num[i]);
            if(c.num[i] >= 10)
            {
                c.num[i+1]++;
                c.num[i] -= 10;
            }
        }
        if(c.num[len])
            len++;
        c.len = len;
        return  c;
    }
    //高精度减法,保证a >= b
    BigNum Sub(BigNum &a, BigNum &b)
    {
        BigNum  c;
        int  i, len;
        len = (a.len > b.len) ? a.len : b.len;
        memset(c.num, 0, sizeof(c.num));
        for(i = 0; i < len; i++)
        {
            c.num[i] += (a.num[i]-b.num[i]);
            if(c.num[i] < 0)
            {
                c.num[i] += 10;
                c.num[i+1]--;
            }
        }
        while(c.num[len] == 0 && len > 1)
            len--;
        c.len = len;
        return  c;
    }
    //高精度乘以低精度,当b很大时可能会发生溢出int范围,具体情况具体分析
    //如果b很大可以考虑把b看成高精度
    BigNum Mul1(BigNum &a, int  &b)
    {
        BigNum c;
        int  i, len;
        len = a.len;
        memset(c.num, 0, sizeof(c.num));
        //乘以0,直接返回0
        if(b == 0)
        {
            c.len = 1;
            return  c;
        }
        for(i = 0; i < len; i++)
        {
            c.num[i] += (a.num[i]*b);
            if(c.num[i] >= 10)
            {
                c.num[i+1] = c.num[i]/10;
                c.num[i] %= 10;
            }
        }
        while(c.num[len] > 0)
        {
            c.num[len+1] = c.num[len]/10;
            c.num[len++] %= 10;
        }
        c.len = len;
        return  c;
    }
    
    //高精度乘以高精度,注意要及时进位,否则肯能会引起溢出,但这样会增加算法的复杂度,
    //如果确定不会发生溢出, 可以将里面的while改成if
    BigNum  Mul2(BigNum &a, BigNum &b)
    {
        int i, j, len = 0;
        BigNum  c;
        memset(c.num, 0, sizeof(c.num));
        for(i = 0; i < a.len; i++)
        {
            for(j = 0; j < b.len; j++)
            {
                c.num[i+j] += (a.num[i]*b.num[j]);
                if(c.num[i+j] >= 10)
                {
                    c.num[i+j+1] += c.num[i+j]/10;
                    c.num[i+j] %= 10;
                }
            }
        }
        len = a.len+b.len-1;
        while(c.num[len-1] == 0 && len > 1)
            len--;
        if(c.num[len])
            len++;
        c.len = len;
        return  c;
    }
    
    //高精度除以低精度,除的结果为c, 余数为f
    void Div1(BigNum &a, int &b, BigNum &c, int &f)
    {
        int  i, len = a.len;
        memset(c.num, 0, sizeof(c.num));
        f = 0;
        for(i = a.len-1; i >= 0; i--)
        {
            f = f*10+a.num[i];
            c.num[i] = f/b;
            f %= b;
        }
        while(len > 1 && c.num[len-1] == 0)
            len--;
        c.len = len;
    }
    //高精度*10
    void  Mul10(BigNum &a)
    {
        int  i, len = a.len;
        for(i = len; i >= 1; i--)
            a.num[i] = a.num[i-1];
        a.num[i] = 0;
        len++;
        //if a == 0
        while(len > 1 && a.num[len-1] == 0)
            len--;
    }
    
    //高精度除以高精度,除的结果为c,余数为f
    void Div2(BigNum &a, BigNum &b, BigNum &c, BigNum &f)
    {
        int  i, len = a.len;
        memset(c.num, 0, sizeof(c.num));
        memset(f.num, 0, sizeof(f.num));
        f.len = 1;
        for(i = len-1;i >= 0;i--)
        {
            Mul10(f);
            //余数每次乘10
            f.num[0] = a.num[i];
            //然后余数加上下一位
            ///利用减法替换除法
            while(Comp(f, b) >= 0)
            {
                f = Sub(f, b);
                c.num[i]++;
            }
        }
        while(len > 1 && c.num[len-1] == 0)
            len--;
        c.len = len;
    }
    void  print(BigNum &a)   //输出大数
    {
        int  i;
        for(i = a.len-1; i >= 0; i--)
            printf("%d", a.num[i]);
        puts("");
    }
    //将字符串转为大数存在BigNum结构体里面
    BigNum ToNum(char *s)
    {
        int i, j;
        BigNum  a;
        a.len = strlen(s);
        for(i = 0, j = a.len-1; s[i] != '\0'; i++, j--)
            a.num[i] = s[j]-'0';
        return  a;
    }
    
    void Init(BigNum &a, char *s, int &tag)   //将字符串转化为大数
    {
        int  i = 0, j = strlen(s);
        if(s[0] == '-')
        {
            j--;
            i++;
            tag *= -1;
        }
        a.len = j;
        for(; s[i] != '\0'; i++, j--)
            a.num[j-1] = s[i]-'0';
    }
    
    int main(void)
    {
        BigNum a, b;
        char  s1[100], s2[100];
        while(scanf("%s %s", s1, s2) != EOF)
        {
            int tag = 1;
            Init(a, s1, tag);    //将字符串转化为大数
            Init(b, s2, tag);
            a = Mul2(a, b);
            if(a.len == 1 && a.num[0] == 0)
            {
                puts("0");
            }
            else
            {
                if(tag < 0) putchar('-');
                print(a);
            }
        }
        return 0;
    }

    这是原文链接blog.csdn.net/hackbuteer1/article/details/6595901

    UVA上有几道高精度题目,总结如下。

    uva424为大数加法

    #include <iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    const int maxn=1<<15;
    struct bignum
    {
        int num[maxn];
        int len;
    };
    
    void tonum(char *s,bignum &a)
    {
        int len=strlen(s);
        a.len=len;
        int i,j;
        for(i=0,j=len-1;j>=0;j--,i++)
        a.num[i]=s[j]-'0';
    }
    
    bignum add(bignum &a,bignum &b)
    {
        int len=(a.len>b.len)?a.len:b.len;
        bignum c;
        memset(c.num,0,sizeof(c.num));
        int i;
        for(i=0;i<len;i++)
        {
            c.num[i]+=(a.num[i]+b.num[i]);
            if(c.num[i]>=10)
            {
                c.num[i]-=10;
                c.num[i+1]++;
            }
        }
        if(c.num[len])
        len++;
        c.len=len;
        return c;
    }
    
    void PRINT(bignum a)
    {
        int i;
        for(i=a.len-1;i>=0;i--)
        printf("%d",a.num[i]);
        printf("\n");
    }
    int main()
    {
        //freopen("test.txt","r",stdin);
        char s[110];
        bignum a;
        a.len=1;
        memset(a.num,0,sizeof(a.num));
        while(scanf("%s",s)!=EOF)
        {
            if(s[0]=='0')
            break;
            bignum b;
            tonum(s,b);
            a=add(a,b);
        }
        PRINT(a);
        return 0;
    }

    uva10106为大数乘法

    #include <iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    const int maxn=1<<15;
    struct bignum
    {
        int num[maxn];
        int len;
    };
    char s1[maxn],s2[maxn];
    
    void tonum(char *s,bignum &a)
    {
        a.len=strlen(s);
        int i,j;
        for(i=0,j=a.len-1;j>=0;j--,i++)
        a.num[i]=s[j]-'0';
    }
    
    bignum MUL(bignum &a,bignum &b)
    {
        bignum c;
        memset(c.num,0,sizeof(c.num));
        int i,j,len;
        for(i=0;i<a.len;i++)
        {
            for(j=0;j<b.len;j++)
            {
                c.num[i+j]+=(a.num[i]*b.num[j]);
                if(c.num[i+j]>=10)
                {
                    c.num[i+j+1]+=c.num[i+j]/10;
                    c.num[i+j]%=10;
                }
            }
        }
        len=a.len+b.len-1;
        while(c.num[len-1]==0&&len>1)
        len--;
        if(c.num[len])
        len++;
        c.len=len;
        return c;
    }
    
    void PRINT(bignum &a)
    {
        int i;
        for(i=a.len-1;i>=0;i--)
        printf("%d",a.num[i]);
        printf("\n");
    }
    int main()
    {
        while(scanf("%s%s",s1,s2)!=EOF)
        {
            bignum a,b,c;
            tonum(s1,a);
            tonum(s2,b);
            c=MUL(a,b);
            PRINT(c);
        }
        return 0;
    }

    uva748是大数求幂

    #include <iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    const int maxn=1<<10;
    int main()
    {
        //freopen("test.txt","r",stdin);
        char R[6];
        int n;
        while(scanf("%s%d",R,&n)!=EOF)
        {
            int s[6],point;
            int i,j;
            for(i=0,j=0;i<6;i++)
            {
                if(R[i]=='.')
                point=i;
                else
                s[j++]=(int)(R[i]-'0');
            }
            point=(5-point)*n-1; //point记录小数点所在位
            int src=s[0]*10000+s[1]*1000+s[2]*100+s[3]*10+s[4];
            int f[maxn];
            memset(f,0,sizeof(f));
            f[0]=1;
            int t,c;
            for(i=1;i<=n;i++)
            {
                c=0;
                for(j=0;j<maxn;j++)
                {
                    t=f[j]*src+c;
                    f[j]=t%10;
                    c=t/10;
                }
            }
            int flag=-1; //需要把小数后面的0消去,需记录小数点后从末端数起有几个连续的零
            for(i=0;i<=maxn;i++)
            {
                if(f[i]) break;
                flag=i;
            }
            if(flag>point) flag=point;
            for(j=maxn-1;j>=0;j--) //消去前面的0
            {
                if(j<=point)
                {
                    if(f[j])
                    break;
                    else
                    {
                        printf(j==point?".0":"0");
                    }
                }
                if(f[j])
                {
                   break;
                }
            }
            for(i=j;i>=0&&i>flag;i--) printf(i==point?".%d":"%d",f[i]);
            printf("\n");
        }
        return 0;
    }

    uva10494是大数除法

    #include <iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int maxn=1<<15;
    char s[maxn];
    struct bignum
    {
        int num[maxn];
        int len;
    };
    
    void PRINT(bignum &a)
    {
        int i;
        for(i=a.len-1;i>=0;i--)
        printf("%d",a.num[i]);
        printf("\n");
    }
    
    void div1(bignum &a,long long &b,bignum &c,long long &f)
    {
        int i,len=a.len;
        memset(c.num,0,sizeof(c.num));
        f=0;
        for(i=a.len-1;i>=0;i--)
        {
            f=f*10+a.num[i];
            c.num[i]=f/b;
            f%=b;
        }
        while(len>1&&c.num[len-1]==0)
        len--;
        c.len=len;
    }
    int main()
    {
        //freopen("test.txt","r",stdin);
        long long b;
        char op[2];
        while(scanf("%s%s%lld",s,op,&b)!=EOF)
        {
            bignum a;
            a.len=strlen(s);
            int i,j=0;
            for(i=a.len-1;s[j]!='\0';i--,j++)
            a.num[j]=s[i]-'0';
             bignum c;
             long long f;
             div1(a,b,c,f);
            if(op[0]=='/')
            {
                PRINT(c);
            }
            else
            {
                printf("%lld\n",f);
            }
        }
        return 0;
    }
  • 相关阅读:
    IO多路复用
    事件驱动模型
    协程
    进程
    py2与py3的编码问题
    Linux Centos7 网卡无法启动
    监控的法则
    如何优雅的采集activeMQ性能指标
    一分钟性能分析
    beta版 tomcat 应用监控指标
  • 原文地址:https://www.cnblogs.com/longlongagocsu/p/2966939.html
Copyright © 2011-2022 走看看