使用线性增加的值填充向量

问题描述 投票:0回答:4

我将填充/初始化具有线性增加值的向量。例如,对于此向量中的每个元素,我希望下一个是a比前一个更多。或者kth元素的值为k*a

这样的事情:

float a = 1.132;
vector<float> v(100);

for (int n = 0; n < 100; ++n)
{
    v[n] = n*a;
}

有更优雅的方式吗?谢谢。

一个matlab的例子是linspace(beginning value, end value, number of points)

linspace(1,5, 6)

ans =

    1.0000    1.8000    2.6000    3.4000    4.2000    5.0000
c++ vector
4个回答
4
投票

你要做的第一件事是切换到使用std::generatestd::generate_n而不是for循环。 generate版本看起来像

int main()
{
    float a = 1.132;
    std::vector<float> v(100);
    std::generate(v.begin(), v.end(), [n = 0, &a]() mutable { return n++ * a; });
}

另一种选择是创建一个迭代器,它将在迭代时生成值。这样做的好处是,您不需要使用任何默认构造值初始化v(这可能是/昂贵的)。然后使用向量范围构造函数,它将初始化所有元素。只要迭代器遵守前向迭代器要求,那么向量将找出所需的空间(如果不是随机访问导致完整迭代),则分配,然后初始化(完全迭代)。对于双重迭代,这可能是昂贵的,因此它可能不会更快,并且可能比生成情况慢(因为零初始化非常快)。


3
投票

如果您可以访问C ++ 11,则可以将std::generate与lambda一起使用:

std::generate(v.begin(), v.end(), [n = 0, &a] () mutable { return a * n++; });

但是,对于这个用例,如评论中所述,几乎不需要矢量。


1
投票

你可以定义一个具有operator++和转换为float的类型,并使用std::iota

#include <algorithm>
#include <vector>

struct spacer
{
    spacer(float scale, int count = 0) : scale(scale), count(count) {}
    spacer operator++(){ ++count; return *this; }
    operator float(){ return count * scale; }
private:
    float scale;
    int count;
};

int main()
{
    std::vector<float> v(100);
    std::iota(v.begin(), v.end(), spacer(1.132));
}

如果你有权访问boost,你可以使用它和boost::counting_iterator实例化你的向量

#include <algorithm>
#include <vector>
#include <tuple>
#include <boost/iterator/counting_iterator.hpp>

struct spacer
{
    spacer(float scale, int count = 0) : scale(scale), count(count) {}
    spacer operator++(){ ++count; return *this; }
    operator float() const{ return count * scale; }
    bool operator==(const spacer & rhs) const{ return std::tie(count, scale) == std::tie(rhs.count, rhs.scale); }
private:
    float scale;
    int count;
};

int main()
{
    using iter = boost::counting_iterator<spacer, std::forward_iterator_tag, std::ptrdiff_t>;
    std::vector<float> v(iter(spacer(1.132)), iter(spacer(1.132, 100)));
}

1
投票

如果你正在寻找像matlab linspace这样的东西,它在C ++中不是直接可用的,但是编写一个函数很容易。喜欢:

std::vector<float> linspace(float start, float end, size_t points)
{
  std::vector<float> res(points);
  float step = (end - start) / (points - 1);
  size_t i = 0;
  for (auto& e : res)
  {
    e = start + step * i++;
  }
  return res;
}

然后你就可以使用它:

int main()
{
  std::vector<float> v = linspace(1, 5, 6);

  for (auto f : v) std::cout << f << " ";
  std::cout << std::endl;

  return 0;
}

输出:

1 1.8 2.6 3.4 4.2 5
© www.soinside.com 2019 - 2024. All rights reserved.