是否有任何数据类型或方法可以计算当前单元格中先前数组单元格的总和?
Posted
技术标签:
【中文标题】是否有任何数据类型或方法可以计算当前单元格中先前数组单元格的总和?【英文标题】:Is there any datatype or method that calculates the sum of previous array cells in the present cell? 【发布时间】:2017-03-24 09:49:36 【问题描述】:例如,如果给定的数组是
1,6,3,2,7.
我想以下面给出的方式将它存储在一个数组中:
1,7,10,12,19
其中 a[2]=a[1]+a[2] 以此类推。
是否有我可以以这种方式存储的任何数据类型或任何可用的方法来计算它而不是使用 for 循环并计算它。
【问题讨论】:
您希望它用于哪种语言...C++ 或 C?它们不是一回事 "而不是使用 for 循环并计算它" --while
循环怎么样? :p
你总是需要一个循环,无论是隐式的还是显式的。为什么这对你很重要?
【参考方案1】:
在 C++ 中,您可以使用 std::partial_sum
(在 <numeric>
内):
std::vector<int> v1,6,3,2,7;
std::partial_sum(v.begin(), v.end(), v.begin());
Demo
【讨论】:
这也是一个循环,伪装的。【参考方案2】:在 c++ 中,一种方法是使用带有状态变换函数的变换算法。
#include <iostream>
#include <iterator>
#include <algorithm>
#include <array>
int main()
// input data
int source[] = 1, 6, 3, 2, 7 ;
// buffer for output data
auto dest = std::array<int, sizeof(source) / sizeof(source[0])> 0 ;
// transform operation
std::transform(std::begin(source),
std::end(source),
std::begin(dest), [tot = 0](auto&& x) mutable return tot += x; );
// emit results
std::copy(std::begin(dest), std::end(dest), std::ostream_iterator<int>(std::cout, ", "));
std::cout << "\n";
更新 - 响应循环问题
这是带有 -O2 的 g++ 的输出。
我们可以看到整个转换是在编译时计算的。没有循环(在这种情况下)。
虽然这是一个极端情况(输入是不可变的并且在编译时已知),但它说明了一个有价值的概念 - std::algorithms 表达意图,不是实现。只要遵守接口的保证,编译器和实现就可以在幕后做自己喜欢的事情。
main: # @main
push rax
mov edi, std::cout
mov esi, 1
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, std::cout
mov esi, .L.str
mov edx, 2
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, std::cout
mov esi, 7
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, std::cout
mov esi, .L.str
mov edx, 2
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, std::cout
mov esi, 10
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, std::cout
mov esi, .L.str
mov edx, 2
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, std::cout
mov esi, 12
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, std::cout
mov esi, .L.str
mov edx, 2
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, std::cout
mov esi, 19
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, std::cout
mov esi, .L.str
mov edx, 2
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, std::cout
mov esi, .L.str.1
mov edx, 1
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
xor eax, eax
pop rcx
ret
【讨论】:
这也是一个循环,伪装的。 @Lundin 这将取决于架构和优化器的质量。我怀疑在上面的示例中,整个转换将在编译时执行,并且简单地发出预先计算的结果。但是,从概念上讲,我明白你的观点。我无法想象在不遍历一个范围的情况下累积部分总和是可能的。 @RichardHodges 所有其他循环也可以展开,因此即使您编写了 for 循环,您也可以说“在这种特殊情况下没有循环。”。但我想我们都同意,在一般的情况下,循环是不可避免的。 @Ctx 是的,甚至并行性也无济于事,因为每个输出元素都依赖于前一个元素。 @RichardHodges 再想一想,如果项目严格按顺序插入到结构中,可以在插入时计算...【参考方案3】:简单地遍历数组。使用变量int previous=0;
,每次赋值时都会更新:
new_array[i] = old_array[i] + previous;
previous = new_array[i];
【讨论】:
这需要一个循环,对吧?除了使用循环之外,OP 还想要其他方法。 @CoolGuy 也许他可以凭空变出数字。以上是关于是否有任何数据类型或方法可以计算当前单元格中先前数组单元格的总和?的主要内容,如果未能解决你的问题,请参考以下文章