简体   繁体   English

如何从C ++向量中删除NAN?

[英]How remove NAN from C++ vector?

I have 我有

std::vector<double>x={1,2,NAN,3, NAN, 4}

when I try x.erase(remove(x.begin(), x.end(), NAN), x.end() , I still see NAN as 当我尝试x.erase(remove(x.begin(), x.end(), NAN), x.end() ,我仍然看到NAN

for (auto i:x)
    std::cout<<i<<" ";

gives

1 2 -nan(ind) 3 -nan(ind) 4

how can I remove the NANs so the output is below? 如何删除NAN,以便输出低于?

1 2 3 4

EDIT: x is a vector of doubles, not ints 编辑: x是双精度矢量,而不是整数

In the weird, wild world of IEEE 754 floating point, NaN != NaN. 在IEEE 754浮点的奇怪,狂野的世界中,NaN!= NaN。 In other words, two not-a-number values do not compare as equal to each other. 换句话说,两个非数字值不相互比较。 So, you cannot simply let std::remove do an equality test. 所以,你不能简单地让std::remove做一个相等的测试。

You need to supply your own predicate that calls a function to determine whether or not a floating-point value is NaN. 您需要提供调用函数的自己的谓词,以确定浮点值是否为NaN。 If you're targeting C++11 or later, the standard library provides such a function: std::isnan . 如果您的目标是C ++ 11或更高版本,则标准库提供了以下功能: std::isnan (If not, the situation is a bit more complicated .) (如果没有, 情况会有点复杂 。)

Putting it all together, then, the correct code would look like this: 把它们放在一起,然后,正确的代码将如下所示:

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


int main()
{
    std::vector<double> x = {
                              1,
                              2,
                              std::numeric_limits<double>::quiet_NaN(),
                              3,
                              std::numeric_limits<double>::quiet_NaN(),
                              4
                            };

    std::cout << "Before removing: ";
    for (auto i : x)
    {
        std::cout << i << " ";
    }
    std::cout << "\n";

    x.erase(std::remove_if(std::begin(x),
                           std::end(x),
                           [](const auto& value) { return std::isnan(value); }),
            std::end(x));

    std::cout << "After removing: ";
    for (auto i : x)
    {
        std::cout << i << " ";
    }

    return 0;
}

In case it got lost in all the demo code, the relevant part is just: 如果它在所有演示代码中丢失,相关部分只是:

x.erase(std::remove_if(std::begin(x),
                       std::end(x),
                       [](const auto& value) { return std::isnan(value); }),
        std::end(x));

where I am passing a lambda to std::remove_if as a unary predicate. 我将lambda传递给std::remove_if作为一元谓词。 It calls std::isnan , passing in the value to check, and it returns the result, which is a Boolean indicating whether or not the value is not-a-number. 它调用std::isnan ,传入要检查的值,然后返回结果,该结果是一个布尔值,表示该值是否为std::isnan -number。 If the predicate returns true, std::remove_if does the removal; 如果谓词返回true,则std::remove_if执行删除操作; otherwise, it doesn't. 否则,它没有。

Note that the logic in floating-point world is typically that NaN values are infectious . 请注意,浮点世界中的逻辑通常是NaN值具有传染性 In other words, any operation involving a NaN will return NaN as a result. 换句话说,任何涉及NaN的操作都将返回NaN作为结果。 So, it strikes me as a bit odd that you're trying to remove all NaN values. 所以,你试图删除所有NaN值有点奇怪。 Be careful not to just shove them under the rug as if they weren't there. 小心不要只是把它们推到地毯下面,好像它们不在那里一样。

This doesn't work, since NAN doesn't equal NAN (this is not specified by C++ standard, but in IEEE 754 standard, which your system probably conforms to). 这不起作用,因为NAN不等于NAN(这不是由C ++标准指定,而是在IEEE 754标准中,您的系统可能符合该标准)。 std::remove , uses equality as the condition to choose elements for removal. std::remove ,使用相等作为条件来选择要删除的元素。

Instead of std::remove , you need to use std::remove_if with a predicate using std::isnan . 而不是std::remove ,你需要使用std::remove_if和一个使用std::isnan的谓词。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM