高精度运算

为了后面课程准备,先把基础的大数高精度运算先实现一遍。

  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  

 

 

 

你可能感兴趣的:(运算)