生成一定范围内的浮点序列

时间:2014-11-17 19:30:00

标签: c++ c++11 stl

我想用vector<float>填充a,从inc开始,增加b,直到vec = 2:0.5:4。所以基本上是Matlab中的vec会做 - { 2.0, 2.5, 3.0, 3.5, 4.0 }现在应该是vector<float> vec(10); float increment = 0.5f; std::generate(begin(vec), end(vec), [&increment]() {static float start = 2.0f; return start += increment ; });

我能想到的最好的是

+1

但显然它不正确,因为它从2.5f开始,而不是2.0f。我想指定参数更简单或更简洁。

我可以想象在一个专门的类中完成它,但这需要相当多的代码。 我也看过std :: iota,但它只能增加 for (float i = -1.0f; i <= 1.0f; i += 0.05f) { vec.emplace_back(i); }

关于最佳,简洁方法的任何想法?使用C ++ 11(以及14的某些部分)欢迎使用。

编辑:当然我也使用过循环,如:

{{1}}

但它有一个问题,即它有时不会达到最终值,就像在这个例子中一样,因为浮点不精确(或者更确切地说是表示)。修复需要一些代码,我认为应该有一个更简洁的方法?

5 个答案:

答案 0 :(得分:4)

您可以编写自己的std::iota变体,它也接受一个步幅参数。

template<typename ForwardIterator, typename T>
void strided_iota(ForwardIterator first, ForwardIterator last, T value, T stride)
{
    while(first != last) {
        *first++ = value;
        value += stride;
    }
}

在您的示例中,您将其用作

std::vector<float> vec(10);
strided_iota(std::begin(vec), std::next(std::begin(vec), 5), 2.0f, 0.5f);

Live demo

答案 1 :(得分:3)

我认为你真的不需要任何花哨的功能。

void fill_vec(vector<float>& vec, float a, float inc, float b)
{
    for(float n = a; n <= b; n += inc)
      vec.push_back(n);
}

如果您担心浮点精度错过了上限,那么您可以添加一小部分(通常用epsilon表示):

float eps = 0.0000001f;
for(float n = a; n <= b + eps; n += inc)

如果您包含<cfloat>,则可以使用FLT_EPSILON,这可能会因平台而异。

答案 2 :(得分:1)

如果问题是你想要包含所有浮点值,那么循环整数并进行必要的计算以返回循环中的浮点值。

for (int i = 20; i <= 40; i += 5) {
        vec.emplace_back(i/10.0);
    }

答案 3 :(得分:1)

您可以使用适用于iotagenerate的仿函数。适当地重载函数调用和递增运算符:

template <typename T>
class ArithmeticProgression
{
    T val;
    T inc;

public:

    ArithmeticProg(T val, T inc) : val(val), inc(inc) {}

    ArithmeticProg& operator++() noexcept(noexcept(val += inc))
    {
        val += inc;
        return *this;
    }

    T operator()() noexcept(noexcept(val += inc))
    {
        auto tmp = val;
        val += inc;
        return tmp;
    }

    operator T() const noexcept {return val;}
};

template <typename T, typename U>
ArProg<typename std::common_type<T, U>::type> makeArithmeticProg( T val, U inc )
{
    return {val, inc};
}

用法:

int main()
{
    std::vector<float> vec;
    std::generate_n(std::back_inserter(vec), 5, makeArithmeticProg(2.0f, 0.5f) );

    for (auto f : vec)
        std::cout << f << ", ";

    std::cout << '\n';

    std::iota( std::begin(vec), std::end(vec), makeArithmeticProg(2.5f, 0.3f) );

    for (auto f : vec)
        std::cout << f << ", ";
}

Demo

答案 4 :(得分:1)

这是一种方法:

#include <iostream>
#include <vector>
#include <algorithm>

// functor
class generator_float
{
    float _start, _inc;
public:
    generator_float(float start, float inc): _start(start), _inc(inc) {};
    float operator()() {
        float tmp = _start;
        _start += _inc;
        return tmp;
    }
};

int main()
{
    std::vector<float> vec(10);
    std::generate(std::begin(vec), std::end(vec), generator_float(2,0.5));
    for(auto&& elem: vec)
        std::cout << elem << " ";
    std::cout << std::endl;
}