zoukankan      html  css  js  c++  java
  • 高精度计算(2015.8.1)

    c++中,变量的大小是有限制的。

    比如int是 -2147483648~2147483647

    long long是-9223372036854775808~18446744073709551615

    然而他们都有一个范围,如果数据过大,就会出现错误。这时,我们需要高精度计算。

    同过数组来存储各位上的情况,模拟计算加减乘除。

    首先,我们定义一个叫做bigNumber的类

    class bigNumber{
    
    };

    然后,在里面声明一个整数数组(1000位)

    int num[1001];

    其中,num[0]保存该数位数,num[i]表示对应数位上的数

    数据的存储方式为(以13为例)

    num 0 1 2 3
    数值 2 1 3 0
    备注 位数 个位 十位 百位

    接着,我们要定义构造函数来初始化它

    要注意,构造函数本身被调用是没什么琴里用的,可以再写一个初始化函数,然后在构造函数里调用它,但需要初始化时,调用初始化函数,而不是构造函数

        bigNumber(){//初始化
            init();
        }
        void init(){
            memset(num,0,sizeof(num));
        }

    然后,就是一些基本的功能的实现

        bigNumber operator = (const bigNumber& rhs){
            init();
            REP(rhs.num[0]+1)num[o]=rhs.num[o];
            return *this;
        }
        bigNumber operator = (long long rhs){
            init();
            int i=1;
            while(rhs){
                num[i]=rhs%10;
                rhs/=10;
                i++;
            }
            num[0]=i-1;
            return *this;
        }
        bool operator < (const bigNumber rhs)const{
            if(num[0]!=rhs.num[0])return (num[0]<rhs.num[0]);
            REP(num[0]){
                int temp=num[0]-o;
                if(num[temp]!=rhs.num[temp])return (num[temp]<rhs.num[temp]);
            }
            return 0;
        }
        bool operator > (const bigNumber rhs)const{
            if(num[0]!=rhs.num[0])return (num[0]>rhs.num[0]);
            REP(num[0]){
                int temp=num[0]-o;
                if(num[temp]!=rhs.num[temp])return (num[temp]>rhs.num[temp]);
            }
            return 0;
        }
        bool operator == (const bigNumber rhs)const{
            return !(*this>rhs||*this<rhs);
        }
        bool operator <= (const bigNumber rhs)const{
            return *this<rhs||*this ==rhs;
        }

     这些都是比较容易实现的,不详细说明了

    而四则运算则相对更为复杂

    首先是加法

    我们先来看一下我们自己是如何计算加法的。

    例如5135+139

    1.对齐数位  5 1 3 5

         +  1 3 9  

    2.从低位开始加,当低位相加后大于9时,把较大数加到下一位上

    而且,我们可以知道,即使是9+9也才等于18。也即计算后,和的位数最多比加数的位数多1

        bigNumber operator + (const bigNumber rhs)const{
            bigNumber temp;
            int len;
            len=num[0]>rhs.num[0]?num[0]:rhs.num[0];
            len++;//两数相加,位数最多比较大的位数多1
            REP(len){
                temp.num[o+1]+=num[o+1]+rhs.num[o+1];
                temp.num[o+2]+=temp.num[o+1]/10;
                temp.num[o+1]%=10;
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }

    而乘法相似,只是是乘数相乘加上进位(乘数与乘数各数位都要乘一次)

         5 1 3 5

     ×      1 3 9  

        4 6 2 1 5

       1 5 4 0 5

       5 1 3 5       

       7 1 3 7 6 5

        bigNumber operator * (const bigNumber rhs)const{
            bigNumber temp;
            int len;
            len=num[0]+rhs.num[0];
            //len++;
            for(int i=1;i<=num[0];i++){
                for(int j=1;j<=rhs.num[0];j++){
                    temp.num[i+j-1]+=num[i]*rhs.num[j];
                    temp.num[i+j]+=temp.num[i+j-1]/10;
                    temp.num[i+j-1]%=10;
                }
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }

    而减法和除法则较为麻烦

    首先,本高精度计算不考虑负数情况,不过负数也并不难写,可以再加上一个bool来储存是否为负数

    不管减数和被减数谁大,都应该是绝对值大的减去绝对值小的(符号相同)

    与加法不同,减法存在借数。不过如果不管需不需要借都借一下,然后如果结果是两位数再进上去更便于书写

    模仿加法稍加修改

        bigNumber operator - (const bigNumber rhs)const{
            bigNumber temp,a,b;
            temp=Max(*this,rhs);
            b=Min(*this,rhs);
            a=temp;
            temp=0;
            int len=a.num[0];
            REP(len){
                temp.num[o+1]+=10+a.num[o+1]-b.num[o+1];
                temp.num[o+2]--;
                temp.num[o+2]+=temp.num[o+1]/10;
                temp.num[o+1]%=10;
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }

    除法是最难写的一部分了,因为牵扯到试商的问题

    我们先来理解一下除法的计算过程(以11311÷12为例)

    1.首先,从被除数的最高位开始除有1÷12=0······1

    2.余数乘10加上被除数的下一位11÷12=0······11

    3.余数乘10加上被除数的下一位113÷12=9······5

    4.余数乘10加上被除数的下一位51÷12=4·····3

    5.余数乘10加上被除数的下一位31÷12=2·····7

    得到答案11311÷12=942······7

    a 0 1 2 3 4 5
    5 1 1 3 1 1

    从右向左读数,分别计算

        bigNumber operator / (const bigNumber rhs)const{
            bigNumber a;
            int it=num[0];
    
            bigNumber d;
            bigNumber c;
    
            while(it>0){
                a=(d*10)+num[it];
                c=c*10;
    
                int t;
                REP(9){
                    if(a < rhs * (o+1)){
                        t=o;
                        break;
                    }
                    t=9;
                }
                c=c+t;
                d=a-rhs*t;
                it--;
            }
            return c;
        }

    改一个字母,就成了取余

        bigNumber operator % (const bigNumber rhs)const{
            bigNumber a;
            int it=num[0];
    
            bigNumber d;
            bigNumber c;
    
            while(it>0){
                a=(d*10)+num[it];
                c=c*10;
    
                int t;
                REP(9){
                    if(a < rhs * (o+1)){
                        t=o;
                        break;
                    }
                    t=9;
                }
                c=c+t;
                d=a-rhs*t;
                it--;
            }
            return d;
        }

    然后是输出函数

        void p(){
            REP(num[0]){
                printf("%d",num[num[0]-o]);
            }
        }

    附上笔记


    以下是完整的bigNumber类

    class bigNumber{
        private:
        int num[1001];
    
        public:
        bigNumber(){
            init();
        }
        void init(){
            memset(num,0,sizeof(num));
        }
        bigNumber operator = (const bigNumber& rhs){
            init();
            REP(rhs.num[0]+1)num[o]=rhs.num[o];
            return *this;
        }
        bigNumber operator = (long long rhs){
            init();
            int i=1;
            while(rhs){
                num[i]=rhs%10;
                rhs/=10;
                i++;
            }
            num[0]=i-1;
            return *this;
        }
        bool operator < (const bigNumber rhs)const{
            if(num[0]!=rhs.num[0])return (num[0]<rhs.num[0]);
            REP(num[0]){
                int temp=num[0]-o;
                if(num[temp]!=rhs.num[temp])return (num[temp]<rhs.num[temp]);
            }
            return 0;
        }
        bool operator > (const bigNumber rhs)const{
            if(num[0]!=rhs.num[0])return (num[0]>rhs.num[0]);
            REP(num[0]){
                int temp=num[0]-o;
                if(num[temp]!=rhs.num[temp])return (num[temp]>rhs.num[temp]);
            }
            return 0;
        }
        bool operator == (const bigNumber rhs)const{
            return !(*this>rhs||*this<rhs);
        }
        bool operator <= (const bigNumber rhs)const{
            return *this<rhs||*this ==rhs;
        }
        bigNumber operator + (const bigNumber rhs)const{
            bigNumber temp;
            int len;
            len=num[0]>rhs.num[0]?num[0]:rhs.num[0];
            len++;
            REP(len){
                temp.num[o+1]+=num[o+1]+rhs.num[o+1];
                temp.num[o+2]+=temp.num[o+1]/10;
                temp.num[o+1]%=10;
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }
        bigNumber operator + (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 + temp2;
        }
        bigNumber operator * (const bigNumber rhs)const{
            bigNumber temp;
            int len;
            len=num[0]+rhs.num[0];
            //len++;
            for(int i=1;i<=num[0];i++){
                for(int j=1;j<=rhs.num[0];j++){
                    temp.num[i+j-1]+=num[i]*rhs.num[j];
                    temp.num[i+j]+=temp.num[i+j-1]/10;
                    temp.num[i+j-1]%=10;
                }
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }
        bigNumber operator * (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 * temp2;
        }
        bigNumber operator - (const bigNumber rhs)const{
            bigNumber temp,a,b;
            temp=Max(*this,rhs);
            b=Min(*this,rhs);
            a=temp;
            temp=0;
            int len=a.num[0];
            REP(len){
                temp.num[o+1]+=10+a.num[o+1]-b.num[o+1];
                temp.num[o+2]--;
                temp.num[o+2]+=temp.num[o+1]/10;
                temp.num[o+1]%=10;
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }
        bigNumber operator - (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 - temp2;
        }
        bigNumber operator / (const bigNumber rhs)const{
            bigNumber a;
            int it=num[0];
    
            bigNumber d;
            bigNumber c;
    
            while(it>0){
                a=(d*10)+num[it];
                c=c*10;
    
                int t;
                REP(9){
                    if(a < rhs * (o+1)){
                        t=o;
                        break;
                    }
                    t=9;
                }
                c=c+t;
                d=a-rhs*t;
                it--;
            }
            return c;
        }
        bigNumber operator / (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 / temp2;
        }
        bigNumber operator % (const bigNumber rhs)const{
            bigNumber a;
            int it=num[0];
    
            bigNumber d;
            bigNumber c;
    
    
    
            while(it>0){
    
                a=(d*10)+num[it];
                c=c*10;
    
                int t;
                REP(9){
                    if(a < rhs * (o+1)){
                        t=o;
                        break;
                    }
                    t=9;
                }
                c=c+t;
                d=a-rhs*t;
                it--;
            }
            return d;
        }
        bigNumber operator % (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 % temp2;
        }
        void p(){
            REP(num[0]){
                printf("%d",num[num[0]-o]);
            }
        }
    };
    点击查看源码

    以下是代测试数据的源码

    #include <cstdio>
    #include <memory>
    #include <cstring>
    using namespace std;
    #define REP(n) for(int o=0;o<n;o++)
    #define Min(a,b) ((a)<(b))?(a):(b)
    #define Max(a,b) ((a)>(b))?(a):(b)
    class bigNumber{
        private:
        int num[1001];
    
        public:
        bigNumber(){
            init();
        }
        void init(){
            memset(num,0,sizeof(num));
        }
        bigNumber operator = (const bigNumber& rhs){
            init();
            REP(rhs.num[0]+1)num[o]=rhs.num[o];
            return *this;
        }
        bigNumber operator = (long long rhs){
            init();
            int i=1;
            while(rhs){
                num[i]=rhs%10;
                rhs/=10;
                i++;
            }
            num[0]=i-1;
            return *this;
        }
        bool operator < (const bigNumber rhs)const{
            if(num[0]!=rhs.num[0])return (num[0]<rhs.num[0]);
            REP(num[0]){
                int temp=num[0]-o;
                if(num[temp]!=rhs.num[temp])return (num[temp]<rhs.num[temp]);
            }
            return 0;
        }
        bool operator > (const bigNumber rhs)const{
            if(num[0]!=rhs.num[0])return (num[0]>rhs.num[0]);
            REP(num[0]){
                int temp=num[0]-o;
                if(num[temp]!=rhs.num[temp])return (num[temp]>rhs.num[temp]);
            }
            return 0;
        }
        bool operator == (const bigNumber rhs)const{
            return !(*this>rhs||*this<rhs);
        }
        bool operator <= (const bigNumber rhs)const{
            return *this<rhs||*this ==rhs;
        }
        bigNumber operator + (const bigNumber rhs)const{
            bigNumber temp;
            int len;
            len=num[0]>rhs.num[0]?num[0]:rhs.num[0];
            len++;
            REP(len){
                temp.num[o+1]+=num[o+1]+rhs.num[o+1];
                temp.num[o+2]+=temp.num[o+1]/10;
                temp.num[o+1]%=10;
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }
        bigNumber operator + (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 + temp2;
        }
        bigNumber operator * (const bigNumber rhs)const{
            bigNumber temp;
            int len;
            len=num[0]+rhs.num[0];
            //len++;
            for(int i=1;i<=num[0];i++){
                for(int j=1;j<=rhs.num[0];j++){
                    temp.num[i+j-1]+=num[i]*rhs.num[j];
                    temp.num[i+j]+=temp.num[i+j-1]/10;
                    temp.num[i+j-1]%=10;
                }
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }
        bigNumber operator * (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 * temp2;
        }
        bigNumber operator - (const bigNumber rhs)const{
            bigNumber temp,a,b;
            temp=Max(*this,rhs);
            b=Min(*this,rhs);
            a=temp;
            temp=0;
            int len=a.num[0];
            REP(len){
                temp.num[o+1]+=10+a.num[o+1]-b.num[o+1];
                temp.num[o+2]--;
                temp.num[o+2]+=temp.num[o+1]/10;
                temp.num[o+1]%=10;
            }
            REP(len){
                if(temp.num[len-o]!=0){
                    temp.num[0]=len-o;
                    break;
                }
            }
            return temp;
        }
        bigNumber operator - (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 - temp2;
        }
        bigNumber operator / (const bigNumber rhs)const{
            bigNumber a;
            int it=num[0];
    
            bigNumber d;
            bigNumber c;
    
            while(it>0){
                a=(d*10)+num[it];
                c=c*10;
    
                int t;
                REP(9){
                    if(a < rhs * (o+1)){
                        t=o;
                        break;
                    }
                    t=9;
                }
                c=c+t;
                d=a-rhs*t;
                it--;
            }
            return c;
        }
        bigNumber operator / (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 / temp2;
        }
        bigNumber operator % (const bigNumber rhs)const{
            bigNumber a;
            int it=num[0];
    
            bigNumber d;
            bigNumber c;
    
    
    
            while(it>0){
    
                a=(d*10)+num[it];
                c=c*10;
    
                int t;
                REP(9){
                    if(a < rhs * (o+1)){
                        t=o;
                        break;
                    }
                    t=9;
                }
                c=c+t;
                d=a-rhs*t;
                it--;
            }
            return d;
        }
        bigNumber operator % (const long long rhs)const{
            bigNumber temp1,temp2;
            temp1=*this;
            temp2=rhs;
            return temp1 % temp2;
        }
        void p(){
            REP(num[0]){
                printf("%d",num[num[0]-o]);
            }
        }
    };
    int main(){
        bigNumber a,b;
        a=9;
        b=9;
        a.p();
        b.p();
        a=a+b;
        printf("
    ");
        a.p();
        printf("
    ");
        a=5135;b=139;
        a=a*b;
        a.p();
        printf("
    ");
        a=9;b=7;
        a=a-b;
        a.p();
        printf("
    ");
        a=12;b=7;
        a=a-b;
        a.p();
        printf("
    ");
        a=11311;b=12;
        a=a/b;
        a.p();
        printf("
    ");
        a=11311;b=12;
        a=a%b;
        a.p();
        printf("
    ");
        return 0;
    }
    点击查看源码
  • 相关阅读:
    Android 走向MD的配色风格
    Android热点回顾第六期
    C#集合类:动态数组、队列、栈、哈希表、字典(转)
    Google Chrome默认字体设置(Win)
    C# Socket的粘包处理(转)
    设计模式原则总结--读《大话设计模式》有感 <转>
    C#设计模式学习笔记-单例模式(转)
    C# 编写Windows Service(windows服务程序)
    C# 获取农历日期
    C# 中怎么将string转换成int型
  • 原文地址:https://www.cnblogs.com/ohyee/p/4690061.html
Copyright © 2011-2022 走看看