小白书--高精度、字符串处理总结

首先要说明的是ACM题目中涉及的基本是初级高精度,直接模拟手算一般不会超时(也可用java),关于高精度的研究还有很多,介绍一个Huge cal库:http://www.emath.ac.cn/hugecalc/

关于字符串,主要增加一些acm入门知识。

以分知识点的形式给出:

1:scanf %c 有其独特的优越性,易于控制。当然getline(cin,str)也是不错的选择,要用到string

2:sprintf()函数,字符串格式化命令,把格式化数据写入某个字符串缓冲区,是个变参函数。(用途:把已经输入的数字转化成字符串形式的快捷方式)

3 : 用scanf获取整行字符串(包括空格)scanf("%[^\n]",str); scanf中的参数:%[ ],意义是限定读入这个集合中的字符,['0','1'....'9']意思是输入数字,如果遇到非数字就停止了,如果集合的第一个字符是"^", 这说明读取不在"^" 后面集合的字符,既遇到"^" 后面集合的字符便停止.注意此时读入的字符串是可以含有空格的。要注意的是,读取一行后要加getchar()以读取缓冲区中的换行符,否则'\n'将出现在下一行的读取中。 借鉴自:http://wangqingyun84.blog.163.com/blog/static/79083617201262691716249/

4:关于gets(str)函数在vim中warning的问题,方法一:直接无视提交或CB中运行两次;方法二:用fgets(str,len,stdin);,len为所定义的str数组长度即可。

5:同样的有fputs(str,stdout);

下面给出C++高精度模板,采集自小白书(有改动),也借鉴了http://blog.csdn.net/mbxc816/article/details/7192461博客。

这里只是分模块的给出,毕竟各自模块的思想都要烂熟于心。

6:

C/C++ string库(string.h)提供了几个字符串查找函数,如下:

 

memchr 在指定内存里定位给定字符
strchr 在指定字符串里定位给定字符
strcspn 返回在字符串str1里找到字符串str2里的任意一个字符之前已查找的字符数量
strrchr 在字符串里定位给定字符最后一次出现的位置
strpbrk 在字符串str1里定位字符串str2里任意一个首次出现的字符
strspn 返回字符串str1从开始字符到第一个不在str2中的字符个数
strstr 在字符串str1中定位字符串str2首次出现的位置

 详细:http://blog.csdn.net/isgray/article/details/6853700

 

1:bign结构体定义

 

const int maxn = 100000;

struct bign{
    int len,s[maxn + 5];

    //初始化与赋值
    bign(){
        memset(s,0,sizeof(s));
        len = 1;//因为0的存在
    }
};

 

 

 

2:bign成员函数 -- 初始化及赋值

 

//初始化与赋值
    bign(){
        memset(s,0,sizeof(s));
        len = 1;//因为0的存在
    }

    bign operator = (const char *num){
        memset(s,0,sizeof(s));
        len = strlen(num);
        for(int i = 0; i < len; ++i)
            s[i] = num[len - i - 1] - '0';//倒序转化成数字
        return *this;
    }

    bign operator = (int num){
        memset(s,0,sizeof(s));
        char ts[maxn + 5];
        sprintf(ts,"%d",num);
        *this = ts;
        return *this;
    }

    bign(int num){
        *this = num;
    }

    bign(const char *num){
        *this = num;
    }
    //bign的str型转化
    string str() const{
        string res = "";
        for(int i = len - 1; i >= 0; --i)
            res +=  (char)(s[i] + '0');
        if(res == "")
            res = "0";
        return res;
    }

 

 

 

3:bign成员函数 -- 四则运算符重载

 //运算符重载
    //高精度加
    bign operator + (const bign & b) const{
        bign sum;
        sum.len = 0;
        for(int i = 0, g = 0; g || i < max(len,b.len); ++i){
            int x = g;//x:暂存和,g:进位
            if(i < len) x += s[i];
            if(i < b.len) x += b.s[i];
            sum.s[sum.len++] = x % 10;
            g = x / 10;
        }
        return sum;
    }

    //高精度减
    bign operator - (const bign & b) const{
        bign dif;
        int maxlen = (len > b.len) ? len : b.len;
        for(int i = 0; i < maxlen; ++i){
            dif.s[i] += s[i] - b.s[i];
            if(dif.s[i] < 0){
                dif.s[i] += 10;
                --dif.s[i + 1];
            }
        }
        dif.len = maxlen;
        while(dif.s[dif.len - 1] == 0 && dif.len > 1)
            --dif.len;
        return dif;
    }

    //高精度乘,实际上加和乘对进位的处理有所不同
    bign operator * (const bign &b) const{
        bign pro;
        pro.len = 0;
        for(int i = 0; i < len; ++i){
            for(int j = 0; j < b.len; ++j){
                pro.s[i + j] += (s[i] * b.s[j]);
                pro.s[i + j + 1] += pro.s[i + j] / 10;
                pro.s[i + j] %= 10;
            }
        }
        pro.len = len + b.len + 1;//这里注意pro.len初始值可能是题目数字范围两倍
        while(pro.s[pro.len - 1] == 0 && pro.len > 1)
            --pro.len;//最后一位不管是不是0都不能让len - 1
        if(pro.s[pro.len])
            ++pro.len;//这句有待商讨
        return pro;
    }

    //高精度乘以低精度
    bign operator * (const int num) const{
        int c = 0,t;
        bign pro;
        for(int i = 0; i < len; ++i){
            t = s[i] * num + c;
            pro.s[i] = t % 10;
            c = t / 10;
        }
        pro.len = len;
        while(c != 0){
            pro.s[pro.len++] = c % 10;
            c /= 10;
        }
        return pro;
    }

    //高精度除,模拟连减
    bign operator / (const bign & b) const{
        bign quo,f;
        for(int i = len - 1; i >= 0; --i){
            f = f * 10;
            f.s[0] = s[i];
            while(f >= b){
                f = f - b;
                ++quo.s[i];
            }
        }
        quo.len = len;
        while(quo.s[quo.len - 1] == 0 && quo.len > 1)
            --quo.len;
        return quo;
    }
    
    //高精度取模
    bign operator % (const bign & b) const{
        bign rem;
        for(int i = len - 1; i >= 0; --i){
            rem = rem * 10;
            rem.s[0] = s[i];
            while(rem >= b){
                rem = rem - b;
            }
        }
        rem.len = len;
        while(rem.s[rem.len - 1] == 0 && rem.len > 1){
            --rem.len;
        }
        return rem;
    }

4:bign成员函数 -- 比较运算符重载及流运算符重载

//比较运算符
    bool operator < (const bign & b) const{
        if(len != b.len) return len < b.len;
        for(int i = len - 1; i >= 0; --i)//从高位开始比较
            if(s[i] != b.s[i])
                return s[i] < b.s[i];
        //如果 本身 == b
        return false;
    }

    bool operator > (const bign &b) const{
        return b < *this;//代表 本身 > b
    }

    bool operator <= (const bign &b) const{
        return !(b < *this);//带表 !(本身 > b)
    }

    bool operator >= (const bign &b) const{
        return !(*this < b);
    }

    bool operator != (const bign &b) const{
        return *this < b || b < *this;
    }

    bool operator == (const bign &b) const{
        return !(*this < b) && !(b < *this);
    }

    friend istream & operator >> (istream & in,bign & x);
    friend ostream & operator << (ostream & out,const bign & x);
//写在bign外部的友元函数
istream & operator >> (istream & in,bign & x){ string ts; in >> ts; x = ts.c_str(); return in; } ostream & operator << (ostream & out,const bign & x){ out << x.str(); return out; } 

 

最后附上总结版:

  1 #include <cstdio>
  2 #include <string>
  3 #include <cstring>
  4 #include <iostream>
  5 using namespace std;
  6 
  7 const int maxn = 100000;
  8 
  9 struct bign{
 10     int len,s[maxn + 5];
 11 
 12     //初始化与赋值
 13     bign(){
 14         memset(s,0,sizeof(s));
 15         len = 1;//因为0的存在
 16     }
 17 
 18     bign operator = (const char *num){
 19         memset(s,0,sizeof(s));
 20         len = strlen(num);
 21         for(int i = 0; i < len; ++i)
 22             s[i] = num[len - i - 1] - '0';//倒序转化成数字
 23         return *this;
 24     }
 25 
 26     bign operator = (int num){
 27         memset(s,0,sizeof(s));
 28         char ts[maxn + 5];
 29         sprintf(ts,"%d",num);
 30         *this = ts;
 31         return *this;
 32     }
 33 
 34     bign(int num){
 35         *this = num;
 36     }
 37 
 38     bign(const char *num){
 39         *this = num;
 40     }
 41     //bign的str型转化
 42     string str() const{
 43         string res = "";
 44         for(int i = len - 1; i >= 0; --i)
 45             res +=  (char)(s[i] + '0');
 46         if(res == "")
 47             res = "0";
 48         return res;
 49     }
 50     //运算符重载
 51     //高精度加
 52     bign operator + (const bign & b) const{
 53         bign sum;
 54         sum.len = 0;
 55         for(int i = 0, g = 0; g || i < max(len,b.len); ++i){
 56             int x = g;//x:暂存和,g:进位
 57             if(i < len) x += s[i];
 58             if(i < b.len) x += b.s[i];
 59             sum.s[sum.len++] = x % 10;
 60             g = x / 10;
 61         }
 62         return sum;
 63     }
 64 
 65     //高精度减
 66     bign operator - (const bign & b) const{
 67         bign dif;
 68         int maxlen = (len > b.len) ? len : b.len;
 69         for(int i = 0; i < maxlen; ++i){
 70             dif.s[i] += s[i] - b.s[i];
 71             if(dif.s[i] < 0){
 72                 dif.s[i] += 10;
 73                 --dif.s[i + 1];
 74             }
 75         }
 76         dif.len = maxlen;
 77         while(dif.s[dif.len - 1] == 0 && dif.len > 1)
 78             --dif.len;
 79         return dif;
 80     }
 81 
 82     //高精度乘,实际上加和乘对进位的处理有所不同
 83     bign operator * (const bign &b) const{
 84         bign pro;
 85         pro.len = 0;
 86         for(int i = 0; i < len; ++i){
 87             for(int j = 0; j < b.len; ++j){
 88                 pro.s[i + j] += (s[i] * b.s[j]);
 89                 pro.s[i + j + 1] += pro.s[i + j] / 10;
 90                 pro.s[i + j] %= 10;
 91             }
 92         }
 93         pro.len = len + b.len + 1;//这里注意pro.len初始值可能是题目数字范围两倍
 94         while(pro.s[pro.len - 1] == 0 && pro.len > 1)
 95             --pro.len;//最后一位不管是不是0都不能让len - 1
 96         if(pro.s[pro.len])
 97             ++pro.len;//这句有待商讨
 98         return pro;
 99     }
100 
101     //高精度乘以低精度
102     bign operator * (const int num) const{
103         int c = 0,t;
104         bign pro;
105         for(int i = 0; i < len; ++i){
106             t = s[i] * num + c;
107             pro.s[i] = t % 10;
108             c = t / 10;
109         }
110         pro.len = len;
111         while(c != 0){
112             pro.s[pro.len++] = c % 10;
113             c /= 10;
114         }
115         return pro;
116     }
117 
118     //高精度除,模拟连减
119     bign operator / (const bign & b) const{
120         bign quo,f;
121         for(int i = len - 1; i >= 0; --i){
122             f = f * 10;
123             f.s[0] = s[i];
124             while(f >= b){
125                 f = f - b;
126                 ++quo.s[i];
127             }
128         }
129         quo.len = len;
130         while(quo.s[quo.len - 1] == 0 && quo.len > 1)
131             --quo.len;
132         return quo;
133     }
134 
135     //高精度取模
136     bign operator % (const bign & b) const{
137         bign rem;
138         for(int i = len - 1; i >= 0; --i){
139             rem = rem * 10;
140             rem.s[0] = s[i];
141             while(rem >= b){
142                 rem = rem - b;
143             }
144         }
145         rem.len = len;
146         while(rem.s[rem.len - 1] == 0 && rem.len > 1){
147             --rem.len;
148         }
149         return rem;
150     }
151     //比较运算符
152     bool operator < (const bign & b) const{
153         if(len != b.len) return len < b.len;
154         for(int i = len - 1; i >= 0; --i)//从高位开始比较
155             if(s[i] != b.s[i])
156                 return s[i] < b.s[i];
157         //如果 本身 == b
158         return false;
159     }
160 
161     bool operator > (const bign &b) const{
162         return b < *this;//代表 本身 > b
163     }
164 
165     bool operator <= (const bign &b) const{
166         return !(b < *this);//带表 !(本身 > b)
167     }
168 
169     bool operator >= (const bign &b) const{
170         return !(*this < b);
171     }
172 
173     bool operator != (const bign &b) const{
174         return *this < b || b < *this;
175     }
176 
177     bool operator == (const bign &b) const{
178         return !(*this < b) && !(b < *this);
179     }
180 
181     friend istream & operator >> (istream & in,bign & x){
182         string ts;
183         in >> ts;
184         x = ts.c_str();
185         return in;
186     }
187     friend ostream & operator << (ostream & out,const bign & x){
188         out << x.str();
189         return out;
190     }
191 };
192 
193 int main(){
194     char st1[maxn + 5],st2[maxn + 5];
195     bign n1,n2;
196     
197     printf("加:");
198     scanf("%s%s",st1,st2);
199     n1 = st1;
200     n2 = st2;
201     cout << n1 + n2 << endl;
202 
203     printf("减:");
204     scanf("%s%s",st1,st2);
205     n1 = st1;
206     n2 = st2;
207     cout << n1 - n2 << endl;
208 
209     printf("乘1:");
210     scanf("%s%s",st1,st2);
211     n1 = st1;
212     n2 = st2;
213     cout << n1 * n2 << endl;
214 
215     printf("乘2:");
216     scanf("%s%s",st1,st2);
217     n1 = st1;
218     n2 = st2;
219     cout << n1 * n2 << endl;
220 
221     printf("除:");
222     scanf("%s%s",st1,st2);
223     n1 = st1;
224     n2 = st2;
225     cout << n1 / n2 << endl;
226     
227     printf("模:");
228     scanf("%s%s",st1,st2);
229     n1 = st1;
230     n2 = st2;
231     cout << n1 % n2 << endl;
232 
233     return 0;
234 }
View Code

 

 

posted @ 2014-06-01 00:52  Naturain  阅读(411)  评论(0编辑  收藏  举报