高精度运算
为了后面课程准备,先把基础的大数高精度运算先实现一遍。
1 为了后面课程准备,先把基础的大数高精度运算先实现一遍。 2 3 //BIGN.h 4 5 #ifndef BIGN_H 6 #define BIGN_H 7 8 #include <iostream> 9 #include <vector> 10 #include <string> 11 using namespace std; 12 const int MAXN = 3000; 13 14 //三元组gcd(a,b) = ax + by = d 15 struct gcd 16 { 17 int x; 18 int y; 19 int d; 20 }; 21 22 23 class bign 24 { 25 private: 26 int n; //参数n 27 gcd m; //定义一个三元组,使用欧几里得算法来进行递归求出最大公因子 28 public: 29 //阶乘的精确值 30 string factorial(int n); 31 32 /** 33 *注:由于我们研究的密码学群Z的范围在{0,1,2,....,n-1}当中 34 *故下面的大数相加,大数相减,大数相乘并没有考虑出现负数的情况 35 */ 36 37 //大数相加 38 string add(string a,string b); 39 40 //大数相减 41 //默认s1>=s2,未处理负数情况 42 string sub(string a,string b); 43 44 //大数相乘 45 //未考虑负数相乘的情况 46 string mul(string a,string b); 47 48 //返回一个十进制数的二进制长度 49 int BitLength(int x); 50 51 //返回x的二进制表示中从低到高的第i位 52 int BitAt(int x,int i); 53 54 //返回值:a^b mod n 的值 55 //通过模重复平方法 56 int Modular_Expoent(int a,int b,int n); 57 58 //返回一个三元组 59 gcd extended_Euclid(int a,int b); 60 61 //模逆运算 62 int inverse(int a,int m); 63 }; 64 65 string bign::factorial(int n) 66 { 67 string result; 68 vector<long long> ff; 69 ff.resize(MAXN); 70 ff[0] = 1; 71 int i,j; 72 for(i = 2;i <= n;i++) 73 { 74 long long c = 0; 75 for(j = 0;j < MAXN;j++) 76 { 77 long long s = ff[j] * i + c; //模拟乘法的过程 78 ff[j] = s % 10; 79 c = s /10; 80 } 81 } 82 for(j = MAXN - 1;j >= 0;j--) 83 { 84 if(ff[j]) 85 break; 86 } 87 for(i = j;i >= 0;i--) 88 { 89 result += (ff[i] + '0'); 90 } 91 return result; 92 } 93 94 95 string bign::add(string a,string b) 96 { 97 string result; 98 string rr; 99 int i; 100 int l1,l2,len1,len2; 101 l1 = len1 = a.size(); 102 l2 = len2 = b.size(); 103 int aa,bb,cc,dd; 104 dd = 0; 105 while(l1 > 0 && l2 > 0) 106 { 107 aa = a[l1-1] - '0'; 108 bb = b[l2-1] - '0'; 109 cc = (aa + bb+dd) % 10; 110 dd = (aa + bb+dd) / 10; 111 result += cc+'0'; 112 l1--; 113 l2--; 114 } 115 while(l1 > 0) 116 { 117 aa = a[l1-1] - '0'; 118 cc = (aa + dd) % 10; 119 dd = (aa + dd) / 10; 120 result += cc + '0'; 121 l1--; 122 } 123 while(l2 > 0) 124 { 125 bb = b[l2-1] - '0'; 126 cc = (bb + dd) % 10; 127 dd = (bb + dd) / 10; 128 result += cc + '0'; 129 l2--; 130 } 131 if(dd == 1) 132 result += '1'; 133 for(i = result.size() - 1;i >= 0 ;i--) 134 rr += result[i]; 135 return rr; 136 } 137 138 string bign::sub(string Max,string Min) 139 { 140 string result; 141 int lmax,lmin; 142 lmax = Max.size(); 143 lmin = Min.size(); 144 int i,j,k; 145 for(i = 0;i <= lmax;i++) 146 result += '0'; 147 result[lmax] = '\0'; 148 lmax--; 149 j = lmax; 150 for(i = lmin - 1;i >= 0;i--,j--) 151 { 152 if(Max[j] - Min[i] >= 0) 153 { 154 result[j] = Max[j] - Min[i] + '0'; 155 } 156 else 157 { 158 result[j] = 10 + Max[j] - Min[i] + '0'; 159 Max[j-1]--; 160 } 161 } 162 while(Max[j] < 0) 163 { 164 Max[j] += 10; 165 Max[j - 1]--; 166 j--; 167 } 168 while(j >= 0) 169 { 170 result[j] = Max[j]; 171 j--; 172 } 173 return result; 174 } 175 176 177 string bign::mul(string aa,string bb) 178 { 179 if(aa == "0" || bb == "0") 180 return "0"; 181 else 182 { 183 string result; 184 int i,j; 185 int len1 = aa.size(); 186 int len2 = bb.size(); 187 for(i = 0,j = len1 - 1;i <= j;i++,j--) 188 { 189 char temp = aa[i]; 190 aa[i] = aa[j]; 191 aa[j] = temp; 192 } 193 for(i = 0,j = len2 - 1;i <= j;i++,j--) 194 { 195 char temp = bb[i]; 196 bb[i] = bb[j]; 197 bb[j] = temp; 198 } 199 vector<int> c; 200 c.resize(MAXN); 201 for(i = 0;i < len1;i++) 202 { 203 for(j = 0;j < len2;j++) 204 { 205 c[i+j] += (aa[i] - '0') * (bb[j] - '0'); 206 } 207 } 208 int k = len1 + len2; 209 for(i = 0;i < k;i++) 210 { 211 if(c[i] > 9) 212 { 213 c[i+1] += c[i] / 10; 214 c[i] %= 10; 215 } 216 } 217 for(i = k - 1;i >= 0;i--) 218 { 219 if(c[i]) 220 break; 221 } 222 for(j = i;j >= 0;j--) 223 { 224 result += (c[j] + '0'); 225 } 226 return result; 227 } 228 } 229 230 int bign::BitLength(int x) 231 { 232 int d = 0; 233 while(x > 0) 234 { 235 x >>= 1; 236 d++; 237 } 238 return d; 239 } 240 241 int bign::BitAt(int x,int i) 242 { 243 return ( x & (1 << (i - 1)) ); 244 } 245 246 int bign::Modular_Expoent(int a,int b,int n) 247 { 248 int i,y = 1; 249 for(i = BitLength(b);i > 0;i--) 250 { 251 y = (y * y) % n; 252 if(BitAt(b,i) > 0) 253 y = (y * a) % n; 254 } 255 return y; 256 } 257 258 gcd bign::extended_Euclid(int a,int b) 259 { 260 gcd aa,bb; 261 if(b == 0) 262 { 263 aa.x = 1; 264 aa.y = 0; 265 aa.d = a; 266 return aa; 267 } 268 else 269 { 270 bb = extended_Euclid(b,a%b); 271 aa.x = bb.y; 272 aa.y = bb.x - (a / b) * bb.y; 273 aa.d = bb.d; 274 } 275 return aa; 276 } 277 278 int bign::inverse(int a,int m) 279 { 280 gcd aa; 281 aa = extended_Euclid(a,m); 282 return aa.x; 283 } 284 #endif 285