大数运算是一类算法应用,在密码学中比较常用。这里先完成一个最基本,最简单的大数运算-大非负整数加法运算。
大整数通常指计算结果超出int存储范围的,亦即会产生溢出的情况。比如32位无符号整数最大为:2^32-1=4294967295
所以接下来的算法就是要完成诸如4294967200 + 4294967220 = 8589934420这样的运算。
解题步骤:
首先,从直观问题入手,为了保证能对任意位数整数进行运算,通常我们要给出两个整数字符串用以相加 str1 + str2,
然后,将str1 与 str2转换成整数数组int a[], b[],逐位进行加法运算,并保留结果与进位值。
注:因为是加法运算,所以结果的位数最多是maxsize(a,b) + 1位
最后,输出结果。
比如 362 + 1698 = 2060
则: num1[] = {2, 6, 3, 0, 0}
num2[] = {8, 9, 6, 1, 0}
从最低位起进行计算:
num1[0] + num2[0] = 2+8 = 10, 则num1[0] = 0, num1[1] = 6+1 = 7
num1[1] + num2[1] = 7+9 = 16, 则num1[1] = 6, num1[2] = 3+1 = 4
num1[2] + num2[2] = 4+6 = 10, 则num1[2] = 0, num1[3] = 0+1 = 1
num1[3] + num2[3] = 1+1 = 2, 则num1[3] = 2, num1[4] = 0+0 = 0
num1[4] + num2[4] = 0+0 = 0, 则num1[4] = 0
现在结果存储在num1[]中{0, 6, 0, 2, 0}, 当然应该反向输出 2060
伪码如下:
string
Add(
string
s1
,
string
s2)
{
int num1 [] <- s1;
int num2 [] <- s2;
int len = max( s1 . length (), s2 . length());
for i = 0 to len - 1
{
num1 [ i ] = num1 [ i ] + num2 [ i ];
if ( num1 [ i ] >= 10)
{
num1 [ i ] -= 10; //将两位整数相加结果的个位保存在num1[i]中
num1 [ i + 1 ] ++; //将两位整数相加结果的十位,即进位加到num1[i+1]中,以备下一步计算
}
}
string res <- num1;
return res;
}
代码实现:
#include <string>
#include <iostream>
#include <cstddef>
#include <algorithm>
using std :: string;
using std :: cout;
using std :: cin;
using std :: max;
using std :: endl;
string Add( const string & s1 , const string & s2)
{
//int num1[] <- s1;
//int num2[] <- s2;
int len = max( s1 . length (), s2 . length());
int * num1 = new int [ len + 1 ];
int * num2 = new int [ len + 1 ];
for ( int i = 0; i <= len; ++ i)
{
num1 [ i ] = 0;
num2 [ i ] = 0;
}
int len1 , len2;
len1 = s1 . length();
len2 = s2 . length();
for ( int i = len1 - 1 , j = 0; i >= 0; -- i , ++ j)
{
num1 [ j ] = s1 [ i ] - '0';
}
for ( int i = len2 - 1 , j = 0; i >= 0; -- i , ++ j)
{
num2 [ j ] = s2 [ i ] - '0';
}
//add every int element in array
for ( int i = 0; i < len; ++ i)
{
num1 [ i ] += num2 [ i ];
if ( num1 [ i ] >= 10)
{
num1 [ i ] -= 10;
num1 [ i + 1 ] ++;
}
}
//store result.
string ret;
if ( len == 1)
{
ret . push_back( '0' + num1 [ 0 ]);
}
else
{
int i = len;
while( num1 [ i ] == 0)
-- i;
for ( i; i >= 0; -- i)
{
ret . push_back( '0' + num1 [ i ]);
}
}
delete [] num1;
delete [] num2;
return ret;
}
int main()
{
string str1 , str2;
cin >> str1 >> str2;
string ret;
ret = Add( str1 , str2);
cout << ret << endl;
return 0;
}
测试用例: 0+0, 1+0, 865799657896+972662725627
#include <iostream>
#include <cstddef>
#include <algorithm>
using std :: string;
using std :: cout;
using std :: cin;
using std :: max;
using std :: endl;
string Add( const string & s1 , const string & s2)
{
//int num1[] <- s1;
//int num2[] <- s2;
int len = max( s1 . length (), s2 . length());
int * num1 = new int [ len + 1 ];
int * num2 = new int [ len + 1 ];
for ( int i = 0; i <= len; ++ i)
{
num1 [ i ] = 0;
num2 [ i ] = 0;
}
int len1 , len2;
len1 = s1 . length();
len2 = s2 . length();
for ( int i = len1 - 1 , j = 0; i >= 0; -- i , ++ j)
{
num1 [ j ] = s1 [ i ] - '0';
}
for ( int i = len2 - 1 , j = 0; i >= 0; -- i , ++ j)
{
num2 [ j ] = s2 [ i ] - '0';
}
//add every int element in array
for ( int i = 0; i < len; ++ i)
{
num1 [ i ] += num2 [ i ];
if ( num1 [ i ] >= 10)
{
num1 [ i ] -= 10;
num1 [ i + 1 ] ++;
}
}
//store result.
string ret;
if ( len == 1)
{
ret . push_back( '0' + num1 [ 0 ]);
}
else
{
int i = len;
while( num1 [ i ] == 0)
-- i;
for ( i; i >= 0; -- i)
{
ret . push_back( '0' + num1 [ i ]);
}
}
delete [] num1;
delete [] num2;
return ret;
}
int main()
{
string str1 , str2;
cin >> str1 >> str2;
string ret;
ret = Add( str1 , str2);
cout << ret << endl;
return 0;
}
测试用例: 0+0, 1+0, 865799657896+972662725627
最后达到的效果应该是理论上可以对任何位大的整数进行计算,只要内存容量允许。