所以,我正在尝试构建一个简单的大整数类,我已经阅读了互联网上的一些页面以及所有这些,但我被卡住了。我知道这个理论,我知道我需要一个进位但是我看到的所有例子,他们更多地关注于chars和10号基础,而且我正在使用不同的方法使它更快一些。我很感激有一些关于加号赋值运算符的帮助,其余的我会试着自己弄明白。
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
class big_integer {
using box = std::vector<int unsigned>;
box data {0};
box split(std::string const & p_input) const {
box output;
for (size_t i {}; i < p_input.size(); i += 8) {
output.push_back(stoi(p_input.substr(i, 8)));
}
return output;
}
public:
big_integer(std::string const & p_data)
: data {split(p_data)}
{}
big_integer(int unsigned const p_data)
: data {p_data}
{}
big_integer & operator +=(big_integer const & p_input) {
int carry {};
for (size_t i {}; i < data.size(); ++i) {
//Need help here!
//All examples I see either use primitive arrays
//or are too esoteric for me to understand.
//data[i] += p_input.data[i] + carry;
}
return *this;
}
std::string to_string() const {
std::string output;
output.reserve(data.size() * 8);
for (auto const i : data) {
output.append(std::to_string(i));
}
return output;
}
};
std::ostream & operator <<(std::ostream & p_output, big_integer const & p_input) {
return p_output << p_input.to_string();
}
int main() {
big_integer test1 {"126355316523"};
big_integer test2 {255};
test1 += test1;
cout << test1 << endl;
cout << test2 << endl;
return 0;
}
答案 0 :(得分:4)
右。所以基本问题是如何unsigned + unsigned + carry
来unsigned
和carry
。如果我们考虑16位整数(它在32位中工作相同,但输入更多),在第一个数字上,0xFFFF + 0xFFFF == 0xFFFE + a进位1.在后续数字0xFFFF + 0xFFFF + carry == 0xFFFF +进位。因此,携带只能是一个。算法是:
unsigned lhs, rhs, carry_in; // Input
unsigned sum, carry_out; // Output
sum = lhs + rhs;
carry_out = sum < lhs ;
sum += carry_in;
carry_out = carry_out || sum < lhs;
基本上,我们的想法是在unsigned
中进行添加,然后检测包装(因此携带)。令人讨厌的是,这是大量条件逻辑和多个指令来实现“add with carry”,这是我用过的每个指令集中的指令。 (注意:可能值得对carry_out
使用|
而不是||
进行最终计算 - 它会保存分支,这对性能有害。一如既往,查看是否有帮助。)
如果你最终会支持乘法,你需要一个比你的“数字”宽两倍的类型 - 在这种情况下,你也可以使用它作为加法。使用上面的变量,假设“unsigned long long”是你的“宽”类型:
const auto temp = (unsigned long long)lhs + rhs + carry_in;
sum = temp; // Will truncate.
carry_out = temp > UINT_MAX;
选择“宽”类型可能会非常棘手。作为第一遍,最好使用uint32_t
表示您的数字,uint64_t
表示您的宽数字。
有关实现多精度算术的更多细节,Chapter 14 from Handbook of Applied Cryptography看起来很有用。