大整数类BigInteger

算法竞赛入门经典(第2版) 第5章C++与STL入门

大整数类BigInteger

跟踪调试后的感悟。

1、=(long long num)该赋值方式实际运用价值不大,输入数据一长容易越界。=(const string& str)赋值方式极具实用价值,只要string不越界,就可以处理该整数。

2、将大整数分块处理,BASE=100000000,WIDTH=8,每八位数为一个单元,进行处理:第一个八位数据的得来,num%BASE;下一个8位数据,num/=BASE;num%BASE;依此类推。

3、此类问题的核心在于四则运算的处理,在看代码之前,猜测,加法难在进位的处理,即不同单元数据衔接(每8位为一个单元),故应从低位向高位处理。

4、函数处理过程中,BigInteger引用&的目的是为使避免不必要的值被复制。

5、每个单元选择8位数理由:32位整数-2^31~2^31-1即-2147483648~2147483647,八位数相加包括进位,最多9位数,没有超过上述整数范围,故本程序,如果只处理加法,极限可以考虑到BASE=1000000000,WIDTH=9。经测试验证通过。

6、四则运算,经跟踪,发现不同单元中进位联系完全靠变量g,程序在此处处理得十分巧妙。

7、通过http://blog.csdn.net/no_retreats/article/details/7853066研究了substr的用法:

string a=s.substr(0,5);       //获得字符串s中 从第0位开始的长度为5的字符串//默认时的长度为从开始位置到尾

8、通过http://blog.csdn.net/nancy_m/article/details/7583550研究了c_str()的用法:

 

c_str() 以 char* 形式传回 string 内含字符串
如果一个函数要求char*参数,可以使用c_str()方法: 
string s = "Hello World!";
printf("%s", s.c_str()); //输出 "Hello World!"

9、通过http://blog.sina.com.cn/s/blog_7b3a697301014a9n.html学习了vector中back()的用法:

返回当前vector容器中末尾元素的引用。

10、力争能独立编码,该代码阅读比想象的要复杂。

11、基本处理思路,从低位向高位处理。如12345678909876543210按如下方式存储于数组中:

s[0]=76543210 s[1]=56789098 s[2]=1234

12、将operator =,operator +放入BigInteger类中,可以减少只用一个参数,另一个默认参数是该类的实例。若放类外部,则要用两个参数。

13、len=(str.length()-1)/WIDTH+1;技巧如下,若有32位,分成(32-1)/8+1=4块;若有31位,分成(31-1)/8+1=4块;若有33位,分成(33-1)/8+1=5块,所有情况通吃,好技巧。

14、vector元素访问可以参考数组,但赋值处理只能用push_back,若用v[i]=x%BASE;会报错,只能用v.push_back(x%BASE);

15、BigInteger分析暂告一段落,已将核心代码研究了,等功力深厚了,再回过头来研究。

 

附上代码:

#include <iostream>
#include <vector>
#include <string>
#include <cstdio>//漏了此句,noi linux下,报错,sscanf,sprintf 未申明 2019-2-16 21:50

using namespace std;

struct BigInteger{
    static const int BASE=100000000;
    static const int WIDTH=8;
    vector<int> v;
    
    BigInteger operator = (const string& s){
        int x;
        int start;
        int end;
        int i;
        int blocks;
        blocks=(s.length()-1)/WIDTH+1;
        for(i=0;i<blocks;i++){
            end=s.length()-i*WIDTH;
            start=max(0,end-WIDTH);
            sscanf(s.substr(start,end-start).c_str(),"%d",&x);//原来写成sscanf(s.substr(start,end).c_str(),"%d",&x);在NoMore549帮助下改正 2019-2-16 21:53
            v.push_back(x);
        }
        
        return *this;
    }
    
    BigInteger operator + (const BigInteger &b){
        BigInteger c;
        int i,g;
        int x;
        for(i=0,g=0;;i++){
            if(g==0&&i>=v.size()&&i>=b.v.size()){//无进位,两个BigInteger实例均已遍历完成
                break;
            }
            x=g;
            if(i<v.size())
                x+=v[i];
            if(i<b.v.size())
                x+=b.v[i];
            c.v.push_back(x%BASE);
            g=x/BASE;
        }
        return c;
    }

};

istream& operator >> (istream &in, BigInteger &b){
    string x;
    in>>x;
    b=x;
    return in;
}

ostream& operator << (ostream &out,const BigInteger &b){
    int i;
    char buf[20];
    out<<b.v.back();//最高位不足8位的预防处理
    for(i=b.v.size()-2;i>=0;i--){
        sprintf(buf,"%08d",b.v[i]);//不足8位补0
        cout<<buf;
    }
    return out;
}
int main(){
    BigInteger a,b;
    cin>>a>>b;
    cout<<a+b<<endl;
    return 0;
}

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值