小白书--高精度、字符串处理总结
首先要说明的是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; }
最后附上总结版:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }