c++ - 任意精度无符号整数仅支持后递增运算符

标签 c++ arbitrary-precision

我正在寻找一个非常简单的 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;
}

最佳答案

为了避免返回变异值,保存一个本地拷贝并返回它:

UNat operator++(int) 
{
    UNat copy = *this;
    // ....
    return copy;
} // don't return by reference

相比之下,前缀运算符确实通过引用返回。

UNat& operator++ ()
{
  // ....
  return *this;
}

来自 Arbitrary-precision arithmetic Explanation 的一些提示和技巧:

1/ When adding or multiplying numbers, pre-allocate the maximum space needed then reduce later if you find it's too much. For example, adding two 100-"digit" (where digit is an int) numbers will never give you more than 101 digits. Multiply a 12-digit number by a 3 digit number will never generate more than 15 digits (add the digit counts).

加法函数的替代实现如下所示:

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++ - 任意精度无符号整数仅支持后递增运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20719376/

相关文章:

c# - Metro 风格混合应用程序 - C# + WebViews 与 JavaScript + WinRT C++ - 最佳选择是什么?

C++:2 + x + 1 与 3 + x 相同吗?

java - 两全其美 : browser and desktop game?

c# - 2^1000 的各位数字和是多少?

c++ - 是否存在允许任意精度指数的 C/C++ 任意精度浮点库?

c - 减去没有二进制补码的有符号二进制数

c++ - 在 Xtext 语法/DSL 中引用 C++ 类型

c++ - 如何使循环考虑多次出现?

c++ - libarb.so : cannot open shared object file: No such file or directory

格式化长数字时,PHP 给出不正确的结果