使用步骤c++构建一个向量

Build a vector with step c++

本文关键字:一个 向量 构建 c++      更新时间:2023-10-16

是否可以在不使用c++中的循环的情况下,用固定的步长创建从一个值到另一个值的向量?

例如,我想用步骤0.5构建一个从1到10的向量。在MATLAB中,我可以这样做:

vector = [1:0.5:10];

c++中有类似的东西吗?

std::generate_n的帮助下,您可以

std::vector<double> v;
const int size = 10 * 2 - 1;
v.reserve(size);
std::generate_n(std::back_inserter(v), size, []() { static double d = 0.5; return d += 0.5; });

实时

您需要一个循环。Matlab只是向您隐藏循环。如果这是你经常做的事情,只需创建一个更容易使用的函数:

#include <vector>
auto make_vector(double beg, double step, double end) 
{
std::vector<double> vec;
vec.reserve((end - beg) / step + 1);
while (beg <= end) {
vec.push_back(beg);
beg += step;
}
return vec;
}
int main() {
auto vec = make_vector(1, 0.5, 10);
}

没有循环是不可能的,但您可以使用例如std::generatestd::generate_n:来隐藏循环

constexpr size_t SIZE = (10 - 1) * 2;
std::vector<double> data(SIZE);
double new_value = 1.0;
std::generate(begin(data), end(data) [&new_value]()
{
double current_value = new_value;
new_value += 0.5;
return current_value;
});

当然,这需要写很多东西,显式循环可能会更好:

std::vector<double> data;
for (double i = 1.0; i <= 10; i += 0.5)
data.push_back(i);

如果步进是"一"(例如11.0(,则可以使用std::iota

std::vector<double> data(10);
std::iota(begin(data), end(data), 1.0);  // Initializes the vector with values from 1.0 to 10.0

不,C++中没有这样的东西。你必须创建一个循环并填充你的向量,所以类似于:

std::vector<double> v;
v.reserve(19);
for(size_t i = 2; i < 21; ++i)
{
v.push_back(i / 2.);
}

我在这里使用的是一个整数循环,而不是一个增量为.5的双循环,以确保我得到的元素数量,并最大限度地减少数值舍入误差(例如,.5很好,但不是1/3(。

使用Ranges-v3库的简单解决方案:

#include <range/v3/all.hpp>
auto make_vector(double min, double step, double max) {
const auto size = static_cast<std::size_t>((max - min) / step);
return ranges::views::iota(std::size_t{0}, size + 1) | 
ranges::views::transform([min, step](auto i) { return min + step * i; }) |
ranges::to<std::vector>();
}
int main() {   
auto vec = make_vector(1, .5, 5);
for (auto x : vec)
std::cout << x << ' ';
// Output: 1 1.5 2 2.5 3 3.5 4 4.5 5
}

范围将是C++20的一部分。

如果您需要做很多这方面的工作,您可以轻松地编写自己的函数,该函数可以与任何容器(支持保留并可由std::generate填充(一起使用:

template <typename TContainer>
TContainer fill(typename TContainer::value_type start, 
typename TContainer::value_type step, 
typename TContainer::value_type end) {
size_t size = static_cast<size_t>((end - start)/step + 1);
TContainer output(size);
std::generate(std::begin(output), std::end(output), 
[&start, step]() { 
return std::exchange(start, start + step);
}
);
return output;
}

然后你可以按如下方式使用它:

auto vec = fill<std::vector<int>>(0, 2, 10);
auto list = fill<std::list<float>>(1, 0.3, 5);

实例

你会得到:

vec: 0, 2, 4, 6, 8, 10
list: 1, 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4, 4.3, 4.6, 4.9