支持仅后增量运算符的任意精度无符号整数 < >我寻找一个非常简单的C++类,它实现了一个具有任意精度的无符号整数,只是一个后增量运算符。
我知道有用于任意精度整数运算的库,但我的需求非常简单,我更喜欢避免一个完整库的重量 在我看来,我当前的实现仍然不够简单,不够优雅。你有什么建议支持仅后增量运算符的任意精度无符号整数 < >我寻找一个非常简单的C++类,它实现了一个具有任意精度的无符号整数,只是一个后增量运算符。,c++,arbitrary-precision,C++,Arbitrary Precision,我知道有用于任意精度整数运算的库,但我的需求非常简单,我更喜欢避免一个完整库的重量 在我看来,我当前的实现仍然不够简单,不够优雅。你有什么建议 #include <vector> #include <string> #include <algorithm> class UNat { public: static const char base = 10; UNat( const char* n ) { std::str
#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;
}
#包括
#包括
#包括
无人值守舱
{
公众:
静态常量字符基=10;
UNat(常量字符*n)
{
std::字符串s(n);
std::reverse(s.begin(),s.end());
对于(大小i=0;i=base){
进位=真;
cc-=基础;
}否则{
进位=假;
}
返回cc;
}
标准::向量n;
};
std::ostream&operator为了避免返回变异值,请保存本地副本并返回:
UNat operator++(int)
{
UNat copy = *this;
// ....
return copy;
} // don't return by reference
相对而言,前缀运算符通过引用返回
UNat& operator++ ()
{
// ....
return *this;
}
以下是一些提示和技巧:
1/当数字相加或相乘时,预先分配最大空间
如果你觉得太多的话,需要减少。例如
加上两个100位数字(其中数字是一个整数)永远不会给出结果
您可以输入超过101个数字。将12位数乘以3位数
数字生成的数字永远不会超过15位(加上数字计数)
加法函数的替代实现如下所示:
c->lastdigit = std::max(a->lastdigit, b->lastdigit)+1;
carry = 0;
for (i=0; i<=(c->lastdigit); i++) {
c->digits[i] = (char) (carry+a->digits[i]+b->digits[i]) % 10;
carry = (carry + a->digits[i] + b->digits[i]) / 10;
}
c->lastdigit=std::max(a->lastdigit,b->lastdigit)+1;
进位=0;
对于(i=0;ilastdigit);(i++){
c->数字[i]=(字符)(进位+a->数字[i]+b->数字[i])%10;
进位=(进位+a->数字[i]+b->数字[i])/10;
}
该代码实现了通常所说的二进制编码十进制(BCD)。非常简单,而且,正如您所说,如果您只想增量,而不需要一般的添加,那么实现可以简单得多。为了进一步简化,请使用数字'0'
到'9'
的内部字符表示,而不是值0
到9
。为了另一种简化,将字符存储在std::string
:
for (int index = 0; index < digits.size(); ++index) {
if (digits[index] != '9') {
++digits[index];
break;
}
digits[index] = '0';
}
if (index == digits.size())
digits.push_back('1');
for(int index=0;index
这使得流插入器几乎变得微不足道。Post increment应该增加值并生成原始值作为表达式结果。似乎您的后增量运算符会生成修改后的值。这就是你需要帮助的问题吗?我想如果你所做的只是增量,ripple carry也没那么糟糕。。。在32位或64位原语而不是8位原语上进行操作可能很好,但8位确实保持了它的简单性。@ebyrob:我从未找到巴贝奇预测方案的良好描述,但帕斯卡(在他之前)使用了一个很好的重力辅助方案。基本上,在加法之前,每个数字轮都必须用手涂底漆。然后,任何一次搬运都会在下一个数字轮上投掷一些东西,给它一个额外的小推力,这些投掷动作可以并行进行。显然是巧妙的。但我不明白它怎么能取消测序(如果你想做的是增加它,你就不需要无限的精确性。在每增加1ns,一个64位的长将至少占用10秒9秒。然后你可以使用C++长和标准的后增量运算符。@ IRA:<代码>长< /C>只有32个比特,所以<代码>长Lo/<代码>会更像它。如果你想要的话。要使用不同的半径,可以在当前位值上使用binary和just以及if-then-else。但这只是制作一个缓慢版本的无限精度。@IraBaxter-可以添加很多钟和口哨。问题是如何使它变得简单,这是我所能看到的最简单的。特别是,支持大于10的基数意味着编写复杂得多的代码来增加单个元素。支持大于10的半径是很简单的。对于基数r,使用值为0到r-1的数字。if语句变成“digits[index]!=”。如果选择r=10^n(选择n=1)然后打印数字就很容易了。@IraBaxter-如果你这样做,流插入器就会变得更复杂;它不能再简单地复制现有的字符值。再说一遍:有很多东西可以以更复杂的代价添加。我的目标是最简单的,而不仅仅是简单的。如果你有其他目标,一定要给出你自己的答案@高度权威的网站Yakk不同意。它区分未压缩的BCD和压缩的BCD。