【问题标题】:Do accumulate() function in C++ adds negative numbers? [closed]C++中的accumulate()函数会加负数吗? [关闭]
【发布时间】:2020-09-29 13:43:55
【问题描述】:
vector<int> nums={1,12,-5,-6,50,3};
int k=4;
int n=nums.size();
for(int i=0;i<=n-k;i++)
    cout<<accumulate(nums.begin()+i,nums.begin()+i+k-1,0)<<" ";

以上代码的输出为:8 1 39

问题是为什么[1,12,-5,-6]之和是8,应该是2=(1+12-5-6)?

与 1 相同,应该是 51=(50+12-5-6),并且

39 也一样,应该是 42=(50+3-6-5)?

【问题讨论】:

  • k-1 其中两个字符不应该存在。
  • 旁白:我会写成for (auto it = nums.begin(); it + k != nums.end(); ++it) std::cout &lt;&lt; accumulate(it, it + k, 0) &lt;&lt; " ";

标签: c++ c++14 accumulate


【解决方案1】:

如果你真的做了accumulate 所做的事情——按顺序添加——并查看每个部分结果,你会看到

1 + 0 = 1
1 + 12 = 13
13 + -5 = 8
8 + -6 = 2

12 + 0 = 12
12 + -5 = 7
7 + -6 = 1
1 + 50 = 51

-5 + 0 = -5
-5 + -6 = -11
-11 + 50 = 39
39 + 3 = 42

此时您可能会发现accumulates 结果是前三个数字的总和,而不是四个。
然后你大声惊呼accumulate 中有一个错误使它忽略了最后一个元素。
然后您查看文档并注意到范围的结尾是“最后一个元素之后的一个”,因此您的结束迭代器nums.begin() + i + 4 - 1 表示它之前的元素(即*(begin() + i + 2),第三个元素from begin() + i) 是范围的最后一个元素。
标准库中的所有迭代器范围(和索引间隔)都以这种方式半开。

解决方案是从结束迭代器中删除-1

【讨论】:

    【解决方案2】:

    如果你的假设是std::accumulate 没有按照常规方式处理负数,那么直接测试一下

    #include <iostream>
    #include <vector>
    #include <numeric>
    
    int main() {
        std::vector<int> nums={1,12,-5,-6,50,3};
        std::cout << std::accumulate(nums.begin(), nums.begin() + 4, 0);
    }
    

    输出为2,对应1 + 12 - 5 - 6

    问题在于您的代码;并在您的迭代器中添加。具体来说,std::accumulate 的前两个参数都与nums.begin() 相关:您需要将第二个参数中的-1 去掉。

    【讨论】:

      【解决方案3】:

      std::accumulate 的第二个参数是就在要处理的最后一个元素之后的位置。

      nums.begin()+i+k-1 中的 -1 阻止处理最后一个要处理的元素,因此您应该删除它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多