使用步骤 c++ 构建向量

Posted

技术标签:

【中文标题】使用步骤 c++ 构建向量【英文标题】:Build a vector with step c++ 【发布时间】:2019-11-07 10:35:03 【问题描述】:

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

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

vector = [1:0.5:10];

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

【问题讨论】:

【参考方案1】:

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; );

LIVE

【讨论】:

【参考方案2】:

你需要一个循环。 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);

【讨论】:

【参考方案3】:

没有循环是不可能的,但您可以隐藏循环,例如使用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

【讨论】:

【参考方案4】:

不,C++ 中没有这样的东西。您必须创建一个循环并填充您的向量,例如:

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

    v.push_back(i / 2.);

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

【讨论】:

【参考方案5】:

使用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_t0, 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 的 part。

【讨论】:

【参考方案6】:

如果您需要做很多这样的事情,您可以轻松编写自己的函数,该函数可以与任何容器一起使用(支持保留并可由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);

Live example

你会得到:

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

【讨论】:

return std::exchange(start, start + step); @Evg Noooice!修改了答案。

以上是关于使用步骤 c++ 构建向量的主要内容,如果未能解决你的问题,请参考以下文章

(C++ STL _ CMake ) —— 利用CMake来构建STL的学习项目的步骤

(C++ STL _ CMake ) —— 利用CMake来构建STL的学习项目的步骤

(C++ STL _ CMake ) —— 利用CMake来构建STL的学习项目的步骤

如何使用 Visual Studio Code 为 cmake 添加预构建步骤?

使用递归的 C++ 中的骑士之旅

Visual Studio 2013 中的“每个文件”自定义构建步骤在哪里?