【问题标题】:Adding values of two separate int vectors with different sizes?添加两个不同大小的独立 int 向量的值?
【发布时间】:2020-04-14 04:46:10
【问题描述】:

我想知道如何将两个向量的值相加,如下所示:

vector<int> v1 = {3, 1, 7};
vector<int> v2 = {6, 5};
vector<int> v3 = {3, 8, 2}; // The sum of v1 and v2

这里的结果应该是 382,因为 317 + 65 得到 382。

有没有办法做到这一点?向量的大小非常棘手。例如,v1 中的第 2 个元素是 1,但 v2 中的第 2 个元素是 5。但是,5 必须添加到 7,而不是 1。

编辑:忘了提到向量可以无限长。转换为 int 然后再转换为向量可能会导致数字丢失。

【问题讨论】:

  • 有没有办法做到这一点? -- 既然这是你问的,答案是“是”。向量可以调整大小 - 只需在较小向量的开头添加 0,使其与较大向量的大小相同。
  • 您是否尝试进行任意长度的加法,其中向量可能是多位数字?
  • 好的。将较小向量的大小调整为等于较大向量后,您只需从后到前迭代,添加到新向量并保存进位,类似于小学课本添加。此外,由于这是一个项目,因此发布解决方案是不明智的 - 如果您善意尝试并陷入困境,那么您可以发布您的代码。
  • 另一个提示——因为你的容器是std::vector,你可能想在做任何事情之前反转向量(见std::reverse)。原因是从长远来看,在处理向量时使用倒数会更有效。对于反向向量,您可以调用push_back,这比尝试在每个数字的长向量的开头插入更有效。然后从前到后迭代,最后反转结果向量。
  • @PaulMcKenzie 这很有道理。反过来实际上很有帮助,因为我一开始使用的是insert,而不是push_back。另外,我没有考虑调整它的大小,在最后添加那些额外的 0。感谢您的建议,非常感谢。

标签: c++ math vector sum add


【解决方案1】:

这是我根据所需条件设计的一种简单方法:(考虑数据类型为DT 的向量v1v2

  • 大小差异:对于向量大小不等的情况,您可以使用 std::vector&lt;&gt;::insert(iterator, 0) 将迭代器设置为开头,简单地在末尾附加 0,因为您需要零首先进行适当的元素到元素添加。不过在此之前,请检查两个向量中哪个更大,然后收集差异并在循环中插入相同的次数:
   int diff;
   if(v1.size() > v2.size())
   {  diff = v1.size() - v2.size();
      for(int i = 0; i < diff; ++i)
          v2.insert(v2.begin(), 0);
   }          
   else
   {  diff = v2.size() - v1.size();
      for(int i = 0; i < diff; ++i)
          v1.insert(v1.begin(), 0);
   }
  • 加法: 现在向量大小相同,您可以使用 functional 标头中的 std::plus 将一个向量(例如 v1)的元素添加到另一个向量(v2 ) 元素方面,在 std::transform 中放置适当的迭代器位置:
std::transform(v1.begin(), v1.end(), v2.begin(), v1.begin(), std::plus<DT>());

这会将v1v2 的元素总和收集到v1(可互换)中。唯一需要处理的问题或条件是元素加法总和大于或等于 10 的情况下的溢出。

  • 溢出:对于向量中除第一个元素(在第 0th 索引处)之外的所有元素,我们需要将1 携带/添加到中的下一个元素溢出的情况 (&gt;=10) 并在除以 10 时将当前向量元素分配给其余数。但是,对于第一个溢出的元素,我们需要将另一个元素分配给向量的开头(例如:{3, 1 } + {9, 2} = {1, 2, 3}) ,这将是 1 (考虑单个数字向量元素),我们可以对其施加单独的 if 语句:
   for(int i = v1.size(); i > 0; --i) 
   { 
       if(i == 1 && v1[1] >= 10)
       {   v1[1] %= 10;
           v1.insert(v1.begin(), 1);
       }     
       else if(i != 1 && v1[i-1] >= 10)
       {  v1[i - 1] %= 10;
          v1[i - 2] += 1;
       }
   }

例子:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#define DT long long int
int main() 
{   
    std::vector<DT> v1 = {5, 2, 5, 7, 8}; 
    std::vector<DT> v2 = {4, 5, 6};  

                         // 52578
                         // 00456
                         // -----
   // Expected output:   // 53034   
   
   // Size management:
   int diff;
   if(v1.size() > v2.size())
   {  diff = v1.size() - v2.size();
      for(int i = 0; i < diff; ++i)
          v2.insert(v2.begin(), 0);
   }          
   else
   {  diff = v2.size() - v1.size();
      for(int i = 0; i < diff; ++i)
          v1.insert(v1.begin(), 0);
   }
   
   // Element-wise addition:
   std::transform(v1.begin(), v1.end(), v2.begin(), v1.begin(),std::plus<DT>());
   
   // Overflow management:
   for(int i = v1.size(); i > 0; --i) 
   { 
       if(i == 1 && v1[1] >= 10)
       {   v1[1] %= 10;
           v1.insert(v1.begin(), 1);
       }     
       else if(i != 1 && v1[i - 1] >= 10)
       {  v1[i - 1] %= 10;
          v1[i - 2] += 1;
       }
   }   
   
   // Display the sum:
   for(auto v:v1)
      std::cout << v;
}

输出:53034

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#define DT long long int
int main() 
{   
    std::vector<DT> v1 = {5, 2, 5, 7}; 
    std::vector<DT> v2 = {9, 3, 7, 2};  

                         //  5257
                         //  9372
                         // -----
   // Expected output:   // 14629   
   
   // Size management:
   int diff;
   if(v1.size() > v2.size())
   {  diff = v1.size() - v2.size();
      for(int i = 0; i < diff; ++i)
          v2.insert(v2.begin(), 0);
   }          
   else
   {  diff = v2.size() - v1.size();
      for(int i = 0; i < diff; ++i)
          v1.insert(v1.begin(), 0);
   }
   
   // Element-wise addition:
   std::transform(v1.begin(), v1.end(), v2.begin(), v1.begin(),std::plus<DT>());
   
   // Overflow management:
   for(int i = v1.size(); i > 0; --i) 
   { 
       if(i == 1 && v1[1] >= 10)
       {   v1[1] %= 10;
           v1.insert(v1.begin(), 1);
       }     
       else if(i != 1 && v1[i-1] >= 10)
       {  v1[i - 1] %= 10;
          v1[i - 2] += 1;
       }
   }   
   
   // Display the sum:
   for(auto v:v1)
      std::cout << v;
} 

输出:14629

【讨论】:

    【解决方案2】:

    你想要这样的东西吗?:

    这段代码,首先将 v1, v2 向量转换为整数 n1, n2

    整数加起来等于n3。

    然后,将整数 n3 再次转换为向量。

    vector<int> v1 = {3, 1, 7};
    vector<int> v2 = {6, 5};
    vector<int> v3;// = {3, 8, 2}; // The sum of v1 and v2
    int n1=0; for(int a:v1) n1=10*n1+a;
    int n2=0; for(int a:v2) n2=10*n2+a;
    int n3 = n1 + n2;
    while(n3) v3.insert(v3.begin(), n3%10),n3/=10;
    //now v3 = {3, 8, 2}
    

    【讨论】:

    • 如果 v1 = {9, 9, 9} 和 v2 = {9, 9, 9},这是否有效?
    • 好的,我测试了它,它适用于超出最高有效数字的进位。
    • 我会赞成你的代码,除了在同一行有这么多语句。使用逗号, 链接表达式的while 语句特别糟糕。
    • 是的,OP 想要任意长的数字,所以这个解决方案在std::numeric_limits&lt;int&gt;::max() 之外无法工作。
    • 为什么会有 3 个赞?这篇文章没有回答 OP 的问题。它只适用于非常小的向量。
    【解决方案3】:

    简单的方法是反向遍历向量。

    std::vector<int>::const_reverse_iterator first = v1.rbegin(), endfirst = v1.rend();
    std::vector<int>::const_reverse_iterator second = v2.rbegin(), endsecond = v2.rend();
    
    //   if adding two digits gives a value of 10 or more, need to carry
    
    int carry = 0;
    std::vector<int> v3(0);
    //  first do summations of digits in reverse until one vector has no more
    
    //   the following loops will collect digits in v3 (the notional "sum" of v1 and v2)
    //      in reverse order
    
    while (first != endfirst && second != endsecond)
    {
    
         int sum = *first + *second + carry;
         carry = (sum >= 10) ? 1 : 0;
         v3.push_back(sum % 10);
         ++first; ++second;
    }
    
    //    if we have reached the end of v1, there may be additional elements in v2, so     
    
    if (first == firstend)
    {
         first = second;
         firstend = secondend;
    }
    
    //   first and firstend specify the range in whichever vector (v1 or v2) has 
    //       more elements
    //    The next loop does nothing if v1 and v2 have the same length
    
    while (first != firstend)
    {
         int sum = *first + carry;
         carry = (sum >= 10) ? 1 : 0;
         v3.push_back(sum % 10);
         ++first;
    }
    
    //   if we are carrying a digit after doing all the sums, then push a 1
    
    if (carry) v3.push_back(1);
    
    //   we have pushed the digits into v3 in reverse order, so ....
    
    std::reverse(v3.begin(), v3.end());
    

    这将处理任何有效长度的向量。 (我将把寻找可以表示无限长度向量的硬件的问题作为一个未解决的挑战)。

    上面的代码假定v1v2 的所有元素都在09 的范围内。可以对其进行简单修改以处理值为10 或更大的元素。我会把它留作练习。

    通过调用v3.reserve() 将元素推入v3 时,可以减少内存分配/重新分配。我会把它留作练习。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-23
      • 2014-01-30
      • 2020-05-22
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多