您的位置:首页 > 其它

有关大数的运算(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;
}
}




总结:大数相关运算在密码学有重要应用,还有很多优化高效的算法,这里只是提出了几种最基本的算法.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: