【发布时间】:2013-12-21 13:12:02
【问题描述】:
我正在寻找一个非常简单的 C++ 类,它实现了一个具有任意精度的无符号整数和后自增运算符。
我知道有用于任意精度整数运算的库,但我的需求非常简单,我更愿意避免完整库的重量。
在我看来,我目前的实现还不够简单,不够优雅。你有什么建议?
#include <vector>
#include <string>
#include <algorithm>
class UNat
{
public:
static const char base = 10;
UNat( const char* n )
{
std::string s(n);
std::reverse(s.begin(),s.end());
for ( size_t i = 0; i < s.length(); i++ ) {
n_.push_back(s[i]-'0');
}
}
UNat& operator++(int)
{
bool carry = false;
bool finished = false;
for ( size_t i = 0; i < n_.size() && !finished; i++ ) {
n_[i] = add(n_[i],1,carry);
if ( carry ) {
finished = false;
} else {
finished = true;
}
}
if ( carry ) {
n_.push_back(1);
}
return *this;
}
std::string to_string() const
{
std::string r(n_.begin(), n_.end());
std::reverse(r.begin(),r.end());
std::for_each(r.begin(), r.end(), [](char& d) { d+='0';});
return r;
}
private:
char add( const char& a, const char& b, bool& carry )
{
char cc = a + b;
if ( cc >= base ) {
carry = true;
cc -= base;
} else {
carry = false;
}
return cc;
}
std::vector< char > n_;
};
std::ostream& operator<<(std::ostream& oss, const UNat& n)
{
oss << n.to_string();
return oss;
}
#include <iostream>
int main()
{
UNat n("0");
std::cout << n++ << "\n";
std::cout << UNat("9")++ << "\n";
std::cout << UNat("99")++ << "\n";
std::cout << UNat("19")++ << "\n";
std::cout << UNat("29")++ << "\n";
std::cout << UNat("39")++ << "\n";
return 0;
}
【问题讨论】:
-
后增量应该增加值并且产生原始值作为表达式结果。您的后增量运算符似乎产生了修改后的值。这是您需要帮助的问题吗?
-
我想如果你所做的只是递增,ripple-carry 还不错......在 32 位或 64 位原语上而不是 8 位上做事情可能会更好但 8 位确实保持简单。
-
@ebyrob:我从来没有找到对 Babbage 预测方案的良好描述,但 Pascal(在他之前)使用了一个很好的重力辅助方案。基本上每个数字轮都必须在添加之前手动启动。然后任何进位都会在下一个数字轮上扔东西,给它一个额外的推动,这些扔动作可以并行进行。很巧妙,很明显。除了我不明白它是如何取消测序的。 :(
-
如果你想做的只是增加它,你几乎不需要无限的精度。每次增量为 1ns,64 位长度至少需要 10^9 秒才能溢出。然后您可以使用 C++ long 和标准的后增量运算符。
-
@Ira:
long只保证是 32 位,所以long long会更像。