在c ++中,将std :: numeric_limits< double> :: max()用作特殊的“标志"是否安全? [英] In c++, is it safe to use std::numeric_limits<double>::max() as a special "flag"?

查看:164
本文介绍了在c ++中,将std :: numeric_limits< double> :: max()用作特殊的“标志"是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出

std::vector<double> a;
std::vector<int> ind;

其中ind 1 升序排列.

我想做以下等同​​的事情:

for (auto it=ind.rbegin();it!=ind.rend();it++) a.erase(a.begin() + *it);

我想到了这个

for (auto it=ind.begin();it!=ind.end();it++) 
   a[*it] = std::numeric_limits<double>::max();
std::erase(std::remove(a.begin(),a.end(),std::numeric_limits<double>::max()),a.end());

这非常快,但是在这种情况下使用std :: numeric_limits :: max()作为标志并不适合.

当然,感觉不应该在等式中发挥太大作用……明确比较std :: remove中的双精度是安全的,并且在实际应用中,此向量中的极限永远不会出现,因此应该还好吧,不是吗?

对此有何想法?


1 )引用解决方案

让我们看看您的基准"代码,说您想执行以下等效"操作:

std::vector<double> a;
std::vector<int> ind;

for (auto it = ind.rbegin(); it != ind.rend(); it++)
    a.erase(a.begin() + *it);

我们从中收集到的是inda中的索引向量,应将其删除,并将它们升序排列.这些索引必须从a中删除.我认为您的目标是在时间和空间上有效地做到这一点.

如果您以所需的最少操作数来考虑,则必须移动a中的许多/大部分/全部元素,以便擦除由ind指示的元素.您不想多次erase(),因为这意味着多次移动某些元素.一种最佳解决方案(通常情况下,不对a中的值施加特殊要求)看起来像这样:

size_t slow = 0; // where we are currently copying "to"
std::vector<int> inditer = ind.begin();
for (size_t fast = 0; fast != a.size(); ++fast) {
    if (inditer != ind.end() && *inditer == fast) {
        // "remove" this element by ignoring it
        ++inditer;
    } else {
        a[slow] = a[fast];
        ++slow;
    }
}
a.resize(slow);

现在,您可能可以使用STL算法和自定义谓词(functor)来重新编写此代码,该谓词可以记住其在ind中的当前"位置,但是代码不会少很多,而且可能很难理解. >

Given

std::vector<double> a;
std::vector<int> ind;

where ind is 1sorted in ascending order.

I want to do the equivalent of the following:

for (auto it=ind.rbegin();it!=ind.rend();it++) a.erase(a.begin() + *it);

I came up with this:

for (auto it=ind.begin();it!=ind.end();it++) 
   a[*it] = std::numeric_limits<double>::max();
std::erase(std::remove(a.begin(),a.end(),std::numeric_limits<double>::max()),a.end());

This is very fast, but it doesn't feel right to use the std::numeric_limits::max() as a flag in this context.

Of course feelings shouldn't play too much into the equation ... clearly comparing the doubles within the std::remove is safe, and the limit will never occur in practice in this vector in a working application, so it should be ok, no?

Any thoughts on this?


1) Ref comment by the OP. – Alf

解决方案

Let's look at your "baseline" code, that you say you want to do the "equivalent" of:

std::vector<double> a;
std::vector<int> ind;

for (auto it = ind.rbegin(); it != ind.rend(); it++)
    a.erase(a.begin() + *it);

What we gather from this is that ind is a vector of indexes in a which should be removed, and that they are sorted ascending. Those indexes must be removed from a. I assume your goal is to do this efficiently in terms of space and time.

If you think about it in terms of the minimum number of operations required, you have to shift many/most/all of the elements in a in order to erase the ones indicated by ind. You don't want to erase() several times because this means shifting some elements more than once. One optimal solution (in the general case, not imposing special requirements on the values in a) looks like this:

size_t slow = 0; // where we are currently copying "to"
std::vector<int> inditer = ind.begin();
for (size_t fast = 0; fast != a.size(); ++fast) {
    if (inditer != ind.end() && *inditer == fast) {
        // "remove" this element by ignoring it
        ++inditer;
    } else {
        a[slow] = a[fast];
        ++slow;
    }
}
a.resize(slow);

Now, you could probably reformulate this using STL algorithms and a custom predicate (functor) which remembers its "current" position in ind, but it will not be much less code and it might be harder to understand.

这篇关于在c ++中,将std :: numeric_limits&lt; double&gt; :: max()用作特殊的“标志"是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆