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

How remove NAN from C++ vector?

我有

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

当我尝试 x.erase(remove(x.begin(), x.end(), NAN), x.end() 时,我仍然将 NAN 视为

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

给予

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

如何删除 NAN 以便输出如下?

1 2 3 4

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

在 IEEE 754 浮点的奇怪、狂野的世界中,NaN != NaN。换句话说,两个 not-a-number 值 而不是 比较彼此相等。所以,你不能简单地让 std::remove 做一个等式测试。

您需要提供自己的谓词来调用一个函数来确定 floating-point 值是否为 NaN。如果你的目标是 C++11 或更高版本,标准库提供了这样一个函数:std::isnan。 (如果没有,the situation is a bit more complicated。)

把它们放在一起,那么正确的代码应该是这样的:

#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;
}

万一它在所有演示代码中都丢失了,相关部分只是:

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

我将 lambda 作为一元谓词传递给 std::remove_if。它调用 std::isnan,传入要检查的值,并返回 return 结果,这是一个布尔值,指示值是否为 not-a-number。如果谓词 return 为真,则 std::remove_if 进行删除;否则,它不会。

请注意,floating-point 世界中的逻辑通常是 NaN 值 具有传染性 。换句话说,任何涉及 NaN 的操作都会 return NaN 作为结果。所以,我觉得你试图删除所有 NaN 值有点奇怪。小心不要把它们推到地毯下,就好像它们不存在一样。

这不起作用,因为 NAN 不等于 NAN(这不是 C++ 标准指定的,而是 IEEE 754 标准指定的,您的系统可能符合该标准)。 std::remove,以相等为条件选择要删除的元素。

而不是 std::remove,您需要将 std::remove_if 与使用 std::isnan 的谓词一起使用。