有关大数的运算(2)
2016-02-15 19:37
246 查看
接着上一篇的内容:接下来实现大数转换成为二进制的代码.
###[0]: string convert_to_bin(string s) { string binary; while(s!="0")//模拟不断的除2取余 { int t = 0,old_t = 0; for (int i = 0; i != s.length(); ++i)//内循环计算一次除法和一次取余运算 { t = (old_t * 10 + s[i] - '0') % 2;//计算余数 s[i] = (s[i]-'0' + old_t* 10) / 2 +'0';//计算除以2的这一位的商 old_t = t;//更新余数 } binary += int_to_string(t); s = remove_pre_zero(s);//获得一次计算后的商 } return string(binary.rbegin(), binary.rend()); }
[1]:实现(x^y)%z的简单形式,其中x,y,z均可以用int表示.
在这里有必要推导一下思路:
假如y的二进制形式可以写为1111111111..11(即2^n-1),那么x^y就可以写为:
[x^1 * x^2*x^4…..*x^(2^n)]。而
**x%z = m1,x^2%z = m1^2%z = m2,
x^4%z = m2^2%z = m3…..最终结果可以表示为(m1*m2*m3……mn)%z;(当y的rn为1的时候)**
那么相应的,y的二进制是r1r2r3…rn时,我们可以采用同样的办法来简化计算,只需要判断相应的二进制位是0(是0就直接判断下一位)还是1
int Power_mod(int x, int y, int z) { //(x^y)%z int mod = 1; int m = x%z; mod = (y & 1 == 1) ? m : 1; while(y/=2)//只要y还不为0 { auto temp = y & 1;//获得y最低位 m = (m*m) % z; if (temp)//如果y二进制形式的这一位是1 mod = (mod*m) % z; } return mod; }
[2]实现(x^y)%z的复杂形式:(x,y,z都是超过20位的巨大数字)
string Power_mod(string x, string y, string z) { string m = Mod(x, z); string y_bin = convert_to_bin(y);//获取y的二进制 string mod = (y_bin.back() == '1') ? m : "1"; for (size_t i = y_bin.length() - 2; i != -1; --i) { m = Mod(multiply(m, m), z); if (y_bin[i] == '1') mod = Mod(multiply(mod, m), z); } return remove_pre_zero(mod); }
main函数:
int main() { cout << Power_mod(17281, 18897821, 22571)<<endl; cout << Power_mod("172222222234566666666663456564365835634144443", "123455555555555255555555555552454232348897821", "222222222222227777777777777777777777777722571"); return 0; }
[5]:进行一定程度的优化,对大数乘法采取分治算法,然后将这个乘法函数代替Power_mod中的乘法,这样计算起来会快一点(大约快1000ms)
string Effective_multiply(string a, string b) { if (a.length() <= 8 && b.length() <=8) return int_to_string(string_to_int(a)*string_to_int(b)); else { string a1 = a.substr(0, a.length() / 2),a2 = a.substr(a.length()/2); string b1 = b.substr(0, b.length() / 2), b2 = b.substr(b.length() / 2); int weight1 = a.length() - (a.length() / 2), weight2 = b.length() - (b.length() / 2); auto s = Effective_multiply(a1, b1) + string( weight1+weight2, '0'); s = add(s, Effective_multiply(a1, b2) + string(weight1, '0')); s =add(s, Effective_multiply(a2, b1) + string(weight2, '0')); s =add(s, Effective_multiply(a2, b2)); return s; } }
总结:大数相关运算在密码学有重要应用,还有很多优化高效的算法,这里只是提出了几种最基本的算法.
相关文章推荐
- 代码签名探析
- Android开发中几个实用的内存查看工具(eclipse)环境下
- 关闭Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用 .
- 151105 - NOIP知识阶段性总结
- 高级数据结构 - 线段树(1)
- 逆序对 - 树状数组求解 - 高级数据结构
- 单调队列
- NOIP2015题目简单分析
- NOIP 2015提高组 题解+分析
- LCA实现的三种不同的方法
- NOIP2015 TG D1T2 message
- NOIP2015 PJ 4 salesman
- NOIP2015 TG D2T1 stone
- 无向树的直径(最长的两点间最短距离)
- iOS应用分发与内测(二)
- 概率论与数理统计复习
- USACO US OPEN 2015 BRONZE 三四题 C++翻译代码
- 对质数的判断
- US 2015 Febrary BRONZE 题解
- 时间复杂度分析在信息学竞赛中的应用