【问题标题】:c++ string (int) + string (int) [duplicate]c ++字符串(int)+字符串(int)[重复]
【发布时间】:2013-03-13 01:21:07
【问题描述】:

我有 2 个字符串,都只包含数字。这些数字大于uint64_t 的最大值。

我怎样才能将这两个数字相加,然后将结果转换为字符串?

【问题讨论】:

  • 您可以使用 bignum 库,或者您可以将字符串切成适合uint64_t 的较小字符串,将它们相加,并将多余的数字带入下一个加法。
  • 您需要一个 big-integer 库(或自己编写)。是时候做一些谷歌搜索了!
  • 最简单的方法是使用专为此类事情设计的pre-made library
  • 另请参阅stackoverflow.com/questions/1218149/…,了解任意精度算术的解释。

标签: c++ string add uint64


【解决方案1】:

好吧,您可以使用更大的数据类型(例如处理大整数的库),也可以快速建立自己的数据类型。

我建议,如果这是一次性的,你可以像你在学校的头几年学到的那样做长加法。您可以直接对两个字符串进行操作,添加列,执行“进位”,然后构建另一个包含结果的字符串。您可以在不进行任何二进制转换的情况下完成所有这些操作。

这里。只是为了好玩,我为你敲了一个解决方案:

string Add( const string& a, const string& b )
{
    // Reserve storage for the result.
    string result;
    result.reserve( 1 + std::max(a.size(), b.size()) );

    // Column positions and carry flag.
    int apos = a.size();
    int bpos = b.size();
    int carry = 0;

    // Add columns
    while( carry > 0 || apos > 0 || bpos > 0 )
    {
        if( apos > 0 ) carry += a[--apos] - '0';
        if( bpos > 0 ) carry += b[--bpos] - '0';
        result.push_back('0' + (carry%10));
        carry /= 10;
    }

    // The result string is backwards.  Reverse and return it.
    reverse( result.begin(), result.end() );
    return result;
}

请注意,为清楚起见,此代码甚至不尝试处理错误。它也不会产生负面影响,但不难解决。

【讨论】:

  • 对总和也很好地使用进位,我以前从未见过这样 - 它很好地减少了代码大小。
【解决方案2】:

您需要一个 BigInt 实现。你可以找到几个不同的here

无论您选择什么 BigInt 实现,都需要与字符串进行转换(他们通常会这样做)。

【讨论】:

    【解决方案3】:

    这是您问题的代码:

    #include <iostream>
    #include <string>
    using namespace std;
    string StrAdd(string a, string b) {
      string::reverse_iterator rit_a = a.rbegin();
      string::reverse_iterator rit_b = b.rbegin();
      string c;
      int val_c_adv = 0;
      while(rit_a != a.rend() && rit_b != b.rend() ) {
        int val_a_i = *rit_a - '0';
        int val_b_i = *rit_b - '0';
        int val_c_i = val_a_i + val_b_i + val_c_adv;
        if(val_c_i >= 10 ) {
          val_c_adv = 1;
          val_c_i -= 10;
        } else {
          val_c_adv = 0;
        }
        c.insert(0,1, (char)(val_c_i+'0'));
        ++rit_a;
        ++rit_b;
      }
      if(rit_a == a.rend() ) {
        while( rit_b != b.rend() ) {
          int val_b_i = *rit_b - '0';
          int val_c_i = val_b_i + val_c_adv;
          if(val_c_i >= 10 ) {
            val_c_adv = 1;
            val_c_i -= 10;
          } else {
            val_c_adv = 0;
          }
          c.insert(0, 1, (char)(val_c_i+'0'));
          ++rit_b;
        }
      } else if( rit_b == b.rend() ) {
        while( rit_a != a.rend() ) {
          int val_a_i = *rit_a - '0';
          int val_c_i = val_a_i + val_c_adv;
          if(val_c_i >= 10 ) {
            val_c_adv = 1;
            val_c_i -= 10;
          } else {
            val_c_adv = 0;
          }
          c.insert(0, 1, (char)(val_c_i+'0'));
          ++rit_a;
        }
      }
      return c;
    }
    
    int main() {
      string res, a, b;
      cout << "a=" << endl;
      cin >> a;
      cout << "b=" << endl;
      cin >> b;
      res = StrAdd(a, b);
      cout << "Result=" << res << endl;    
    }
    

    【讨论】:

      【解决方案4】:

      如果您只想处理正数而不必担心引入像 GMP 这样的整个 bignum 库(以及它倾向于中止内存不足错误,我认为这在通用库中是不可原谅的) ,您可以自己滚动,例如:

      static std::string add (const std::string& num1, const std::string& num2) {
          // Make num1 the wider number to simplify further code.
      
          int digit, idx1 = num1.length() - 1, idx2 = num2.length() - 1;
          if (idx1 < idx2) return add (num2, num1);
      
          // Initialise loop variables.
      
          int carry = 0;
          std::string res;  // reserve idx1+2 chars if you want.
      
          // Add digits from right until thinner number finished.
      
          while (idx2 >= 0) {
              digit = num1[idx1--] - '0' + num2[idx2--] - '0' + carry;
              carry = (digit > 9);
              res.insert (0, 1, (digit % 10) + '0');
          }
      
          // Then just process rest of wider number and any leftover carry.
      
          while (idx1 >= 0) {
              digit = num1[idx1--] - '0' + carry;
              carry = (digit > 9);
              res.insert (0, 1, (digit % 10) + '0');
          }
          if (carry) res.insert (0, 1, '1');
      
          return res;
      }
      

      您可以添加效率,例如提前在目标字符串中保留空间,并设置它的特定索引而不是插入,但是,除非您正在处理真正的 大量 字符串或这样做很多 每秒时间,我通常更喜欢更易于理解和维护的代码。

      【讨论】:

        猜你喜欢
        • 2013-09-14
        • 2017-03-25
        • 1970-01-01
        • 2011-05-25
        • 2018-03-06
        • 2020-08-27
        • 1970-01-01
        • 2012-10-06
        • 2013-12-08
        相关资源
        最近更新 更多