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

use*_*619 3 c++ nan

我有

std::vector<double>x={1,2,NAN,3, NAN, 4}
Run Code Online (Sandbox Code Playgroud)

当我尝试x.erase(remove(x.begin(), x.end(), NAN), x.end(),我仍然看到NAN作为

for (auto i:x)
    std::cout<<i<<" ";
Run Code Online (Sandbox Code Playgroud)

1 2 -nan(ind) 3 -nan(ind) 4
Run Code Online (Sandbox Code Playgroud)

如何删除NAN,所以输出如下?

1 2 3 4
Run Code Online (Sandbox Code Playgroud)

编辑:x是双精度的向量,而不是整数

Cod*_*ray 8

在IEEE 754浮点的怪异,荒野的世界中,NaN!= NaN。换句话说,两个非数字值彼此相等。因此,您不能简单地std::remove进行相等性测试。

您需要提供自己的谓词,以调用函数来确定浮点值是否为NaN。如果您的目标是C ++ 11或更高版本,则标准库提供了这样的功能:std::isnan。(如果不是这样,情况就更复杂了。)

将它们放在一起,正确的代码将如下所示:

#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;
}
Run Code Online (Sandbox Code Playgroud)

如果它在所有演示代码中迷失了,相关部分就是:

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

我将lambda传递给std::remove_if一元谓词。它调用std::isnan,传入值进行检查,然后返回结果,该结果是一个布尔值,指示该值是否为非数字。如果谓词返回true,std::remove_if则执行移除;否则,事实并非如此。

请注意,浮点世界的逻辑通常是NaN值具有传染性。换句话说,任何涉及NaN的操作都将返回NaN作为结果。因此,您尝试删除所有NaN值使我感到有些奇怪。注意不要将它们像不在那里一样推到地毯下面。