我有两个字符串,都只包含数字。这些数字大于uint64_t
的最大值。
我怎样才能添加这两个数字,然后将结果转换为字符串?
答案 0 :(得分:5)
好吧,你可以使用更大的数据类型(例如处理大整数的库),或者你可以快速敲击自己的数据类型。
我建议如果这是一次性的话,你会做很长时间的补充,就像你在学校开始的几年里学到的那样。您可以直接在两个字符串上操作,添加列,执行'carry',并构建包含结果的另一个字符串。您无需转换为二进制文件即可完成所有这些操作。
下面。为了好玩,我为你找到了一个解决方案:
string Add( const string& a, const string& b )
{
// Reserve storage for the result.
string result;
result.reserve( 1 + std::max(a.size(), b.size()) );
// Column positions and carry flag.
int apos = a.size();
int bpos = b.size();
int carry = 0;
// Add columns
while( carry > 0 || apos > 0 || bpos > 0 )
{
if( apos > 0 ) carry += a[--apos] - '0';
if( bpos > 0 ) carry += b[--bpos] - '0';
result.push_back('0' + (carry%10));
carry /= 10;
}
// The result string is backwards. Reverse and return it.
reverse( result.begin(), result.end() );
return result;
}
请注意,为清楚起见,此代码甚至不会尝试处理错误。它也没有做否定,但要解决这个问题并不难。
答案 1 :(得分:1)
您需要一个BigInt实现。你可以找到几个不同的here。
无论你选择哪种BigInt实现,都需要转换为字符串(通常是字符串)。
答案 2 :(得分:1)
如果您只是想处理正数而不必担心引入像GMP这样的整个bignum库(以及它只是在内存错误上中止的倾向,我发现在通用库中是不可原谅的) ,你可以自己动手,比如:
static std::string add (const std::string& num1, const std::string& num2) {
// Make num1 the wider number to simplify further code.
int digit, idx1 = num1.length() - 1, idx2 = num2.length() - 1;
if (idx1 < idx2) return add (num2, num1);
// Initialise loop variables.
int carry = 0;
std::string res; // reserve idx1+2 chars if you want.
// Add digits from right until thinner number finished.
while (idx2 >= 0) {
digit = num1[idx1--] - '0' + num2[idx2--] - '0' + carry;
carry = (digit > 9);
res.insert (0, 1, (digit % 10) + '0');
}
// Then just process rest of wider number and any leftover carry.
while (idx1 >= 0) {
digit = num1[idx1--] - '0' + carry;
carry = (digit > 9);
res.insert (0, 1, (digit % 10) + '0');
}
if (carry) res.insert (0, 1, '1');
return res;
}
您可以提前提高效率,例如预先在目标字符串中保留空间,并设置它的特定索引而不是插入,除非您正在处理真正的大量字符串或执行许多每秒的时间,我通常更喜欢更易于理解和维护的代码。
答案 3 :(得分:1)
以下是您的问题的代码:
#include <iostream>
#include <string>
using namespace std;
string StrAdd(string a, string b) {
string::reverse_iterator rit_a = a.rbegin();
string::reverse_iterator rit_b = b.rbegin();
string c;
int val_c_adv = 0;
while(rit_a != a.rend() && rit_b != b.rend() ) {
int val_a_i = *rit_a - '0';
int val_b_i = *rit_b - '0';
int val_c_i = val_a_i + val_b_i + val_c_adv;
if(val_c_i >= 10 ) {
val_c_adv = 1;
val_c_i -= 10;
} else {
val_c_adv = 0;
}
c.insert(0,1, (char)(val_c_i+'0'));
++rit_a;
++rit_b;
}
if(rit_a == a.rend() ) {
while( rit_b != b.rend() ) {
int val_b_i = *rit_b - '0';
int val_c_i = val_b_i + val_c_adv;
if(val_c_i >= 10 ) {
val_c_adv = 1;
val_c_i -= 10;
} else {
val_c_adv = 0;
}
c.insert(0, 1, (char)(val_c_i+'0'));
++rit_b;
}
} else if( rit_b == b.rend() ) {
while( rit_a != a.rend() ) {
int val_a_i = *rit_a - '0';
int val_c_i = val_a_i + val_c_adv;
if(val_c_i >= 10 ) {
val_c_adv = 1;
val_c_i -= 10;
} else {
val_c_adv = 0;
}
c.insert(0, 1, (char)(val_c_i+'0'));
++rit_a;
}
}
return c;
}
int main() {
string res, a, b;
cout << "a=" << endl;
cin >> a;
cout << "b=" << endl;
cin >> b;
res = StrAdd(a, b);
cout << "Result=" << res << endl;
}