【问题标题】:Handling large numbers in C++?在 C++ 中处理大量数字?
【发布时间】:2010-09-12 03:48:16
【问题描述】:

在 C++ 中处理大型数字输入的最佳方法是什么(例如 10^100)?

对于算法,我通常会切换到 ruby​​,有时我会使用字符串。

还有什么好的方法吗?

【问题讨论】:

  • 我试图澄清一下。如果我误解了,请随时纠正我
  • 谢谢先生。感谢图书馆..但我想知道还有其他方法吗?我的意思是不使用特定的 stl .. 我使用了链表!!

标签: c++ biginteger largenumber


【解决方案1】:

听起来您正在寻找一种输入任意精度数字的方法。 这里有两个你可以使用的库:GMPMAPM

【讨论】:

    【解决方案2】:

    查看 Owen Astrachan 的 The Large Integer Case Study in C++.pdf。我发现这个文件对详细介绍和代码实现非常有用。它不使用任何第 3 方库。我用它来处理大量数字(只要你有足够的内存来存储vector<char>)没有问题。


    想法: 它通过将 big int 存储在 vector<char> 中来实现任意精度的整数类。

    vector<char> myDigits; // stores all digits of number
    

    那么所有与大int相关的操作,包括&lt;&lt;, &gt;&gt;, +, -, *, ==, &lt;, !=, &gt;, etc.,都可以基于对这个char array的操作来完成。


    代码的味道: 这是头文件,你可以在pdf文件中找到它的cpp和代码。

    #include <iostream>
    #include <string> // for strings
    #include <vector> // for sequence of digits
    using namespace std;
    
    class BigInt
    {
    public:
        BigInt(); // default constructor, value = 0
        BigInt(int); // assign an integer value
        BigInt(const string &); // assign a string
        // may need these in alternative implementation
        // BigInt(const BigInt &); // copy constructor
        // ~BigInt(); // destructor
        // const BigInt & operator = (const BigInt &);
        // assignment operator
        // operators: arithmetic, relational
        const BigInt & operator += (const BigInt &);
        const BigInt & operator -= (const BigInt &);
        const BigInt & operator *= (const BigInt &);
        const BigInt & operator *= (int num);
        string ToString() const; // convert to string
        int ToInt() const; // convert to int
        double ToDouble() const; // convert to double
        // facilitate operators ==, <, << without friends
        bool Equal(const BigInt & rhs) const;
        bool LessThan(const BigInt & rhs) const;
        void Print(ostream & os) const;
    private:
        // other helper functions
        bool IsNegative() const; // return true iff number is negative
        bool IsPositive() const; // return true iff number is positive
        int NumDigits() const; // return # digits in number
        int GetDigit(int k) const;
        void AddSigDigit(int value);
        void ChangeDigit(int k, int value);
        void Normalize();
        // private state/instance variables
        enum Sign{positive,negative};
        Sign mySign; // is number positive or negative
        vector<char> myDigits; // stores all digits of number
        int myNumDigits; // stores # of digits of number
    };
    
    // free functions
    ostream & operator <<(ostream &, const BigInt &);
    istream & operator >>(istream &, BigInt &);
    BigInt operator +(const BigInt & lhs, const BigInt & rhs);
    BigInt operator -(const BigInt & lhs, const BigInt & rhs);
    BigInt operator *(const BigInt & lhs, const BigInt & rhs);
    BigInt operator *(const BigInt & lhs, int num);
    BigInt operator *(int num, const BigInt & rhs);
    bool operator == (const BigInt & lhs, const BigInt & rhs);
    bool operator < (const BigInt & lhs, const BigInt & rhs);
    bool operator != (const BigInt & lhs, const BigInt & rhs);
    bool operator > (const BigInt & lhs, const BigInt & rhs);
    bool operator >= (const BigInt & lhs, const BigInt & rhs);
    bool operator <= (const BigInt & lhs, const BigInt & rhs);
    

    【讨论】:

      【解决方案3】:

      您是否正在寻找如何对收到的大量输入执行操作?有一个big integer C++ 库(类似于Java)允许您执行算术运算...

      【讨论】:

        【解决方案4】:

        如果您希望为此目的编写自己的代码,请尝试使用字符串来存储大数字...然后您可以在它们上创建基本的操作,例如 + - / *... 例如 -

        #include <iostream>
        
        using namespace std;
        
        string add (string &s1, string &s2){
            int carry=0,sum,i;
        
            string  min=s1,
            max=s2,
            result = "";
        
            if (s1.length()>s2.length()){
                max = s1;
                min = s2;
            } else {
                max = s2;
                min = s1;
            }
        
            for (i = min.length()-1; i>=0; i--){
                sum = min[i] + max[i + max.length() - min.length()] + carry - 2*'0';
        
                carry = sum/10;
                sum %=10;
        
                result = (char)(sum + '0') + result;
            }
        
            i = max.length() - min.length()-1;
        
            while (i>=0){
                sum = max[i] + carry - '0';
                carry = sum/10;
                sum%=10;
        
                result = (char)(sum + '0') + result;
                i--;
            }
        
            if (carry!=0){
                result = (char)(carry + '0') + result;
            }       
        
            return result;
        }
        
        int main (){
            string a,b;
        
            cin >> a >> b;
        
            cout << add (a,b)<<endl;
        
            return 0;
        }
        

        【讨论】:

          【解决方案5】:

          假设您正在谈论输入数字,双精度将使您达到 1.7976931348623157 x 10^308

          【讨论】:

            【解决方案6】:

            您可能想看看gmplib,这是一个用于 C 和 C++ 的任意精度数字处理库

            【讨论】:

              【解决方案7】:

              如果您希望它准确,您需要一个用于处理大数字的库。 Java 有 BigInt,无论你想取多少位数,它总是准确的,并提供对它们的数学运算。所有的源代码都包含在内,你可以转移它,但这真的不是 C++ 最擅长的——我会使用基于 JVM 的语言并使用其中一个大库。

              我不认为我会为此使用 ruby​​,除非您希望它变慢,并且我假设由于您在谈论 C++,因此速度在某种程度上是设计考虑因素。

              【讨论】:

                【解决方案8】:

                正如其他人已经指出的那样,C++ 中有各种大数/任意精度库,您可能会发现它们很有用。如果不需要速度,我的印象是 Python 和 Lisp 默认都使用 bignums。

                【讨论】:

                • 这对 Liso 来说是正确的。如果我在做 bignum 的事情,我会使用 Lisp。 :)
                • @Paul Nathan > 这对 Liso 来说是正确的。你是说Lisp吗?还是 Liso 是我不知道的某个图书馆?
                【解决方案9】:

                考虑boost::cpp_int

                #include <boost/multiprecision/cpp_int.hpp>
                #include <iostream>
                
                int main()
                {
                   using namespace boost::multiprecision;
                
                   cpp_int u = 1;
                   for(unsigned i = 1; i <= 100; ++i)
                      u *= i;
                
                   // prints 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 (i.e. 100!)
                   std::cout << u << std::endl;
                
                   return 0;
                }
                

                【讨论】:

                  【解决方案10】:

                  嗯,我认为进行此类算术计算的最佳方法是使用字符串。将输入作为命令行参数提供,然后使用 atoi()itoa() 等字符串函数操作整个逻辑!但是,嘿,这可以用于乘法和除法吗?我认为以这种方式输入的字符串strlen 对编译器的编程无关紧要,直到逻辑正常。

                  【讨论】:

                  • 这不是一个好的解决方案。从命令行参数获取输入会使您的程序毫无用处,除非您正在制作一种命令行计算器。此外,使用ato* 函数都假定您已经知道所需的数据类型并且它们将在标准精度范围内,因此浪费时间转换为它们而不是直接转换为大数字格式是没有意义的' 只需要再次解析这些数字,假设您甚至正确地阅读了它们。 itoa 也不是标准 C++ 库的一部分。
                  猜你喜欢
                  • 1970-01-01
                  • 2021-08-06
                  • 1970-01-01
                  • 2012-03-03
                  • 1970-01-01
                  • 2016-06-19
                  • 2013-07-10
                  • 1970-01-01
                  • 2016-02-29
                  相关资源
                  最近更新 更多