我想用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}}
但它有一个问题,即它有时不会达到最终值,就像在这个例子中一样,因为浮点不精确(或者更确切地说是表示)。修复需要一些代码,我认为应该有一个更简洁的方法?
答案 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);
答案 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)
您可以使用适用于iota
和generate
的仿函数。适当地重载函数调用和递增运算符:
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 << ", ";
}
答案 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;
}