У меня есть 2 строки, оба содержат только числа. Эти цифры больше, чем максимум uint64_t
.C++ string (int) + string (int)
Как я могу добавить эти 2 числа, а затем преобразовать результат в строку?
У меня есть 2 строки, оба содержат только числа. Эти цифры больше, чем максимум uint64_t
.C++ string (int) + string (int)
Как я могу добавить эти 2 числа, а затем преобразовать результат в строку?
Ну, вы можете использовать больший тип данных (например, библиотеку, которая имеет дело с большими целыми числами), или вы можете быстро сбить свой собственный.
Я бы предположил, что если это одно, вы делаете длинное дополнение точно так же, как вы бы научились делать в первые несколько лет обучения в школе. Вы можете напрямую работать с двумя строками, добавлять столбцы, выполнять «перенос» и строить другую строку, содержащую результат. Вы можете сделать все это без преобразования в двоичный код или из него.
Здесь. Просто для удовольствия, я залетела для вас решение:
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;
}
Обратите внимание, что для ясности, этот код не даже пытаться обрабатывать ошибки. Он также не делает негативов, но это не сложно исправить.
Хорошее использование переноса для суммы, а также, я не видел, чтобы это делалось так раньше - это значительно уменьшает размер кода. – paxdiablo
Вам нужна реализация BigInt. Вы можете найти несколько разных here.
Независимо от того, какой вариант реализации BigInt вы выбрали, требуется преобразование в строку и из нее (как правило, это делается).
Если вы просто хотите обрабатывать положительные числа, не беспокоясь о том, чтобы собрать всю библиотеку бигмуна, такую как GMP (наряду с тенденцией просто прерывать ошибки из-за памяти, что-то, что я считаю непростительным в библиотеке общего назначения), вы можете свернуть свое собственное, что-то вроде:
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;
}
вы можете добавить эффективность как резервирование места в целевой строке заранее, и установление конкретных показателей его, а не вставлять, но, если вы не обработки действительно массив строки или делать это many время в секунду, я обычно предпочитаю код, который проще понять и поддерживать.
Вот код для Вашего вопроса:
#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;
}
Вы можете использовать bignum библиотеку, или вы можете нарезать строки на меньшие строки, которые вписываются в 'uint64_t', добавить их, и нести дополнительные цифры к следующему добавлению. –
Вам понадобится библиотека * big-integer * (или напишите самостоятельно). Пора сделать что-нибудь в Google! –
Самый простой подход - использование [готовой библиотеки] (http://www.boost.org/libs/multiprecision/), предназначенной только для таких вещей. – ildjarn