我有
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
是双精度而不是整数的矢量
答案 0 :(得分:7)
在IEEE 754浮点的怪异,狂野的世界中,NaN!= NaN。换句话说,两个非数字值 not 彼此相等。因此,您不能简单地让std::remove
进行相等性测试。
您需要提供自己的谓词,该谓词调用函数来确定浮点值是否为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
,传入要检查的值,然后返回结果,该结果是一个布尔型布尔值,指示该值是否为非数字。如果谓词返回true,则std::remove_if
进行删除;否则,不会。
请注意,浮点世界中的逻辑通常是NaN值具有传染性。换句话说,任何涉及NaN的操作都将返回NaN作为结果。因此,您尝试删除所有NaN值使我感到有些奇怪。注意不要只是将它们推到地毯下面,就好像它们不在那里一样。
答案 1 :(得分:2)
这是行不通的,因为NAN不等于NAN(这不是C ++标准指定的,但是在您的系统可能符合的IEEE 754标准中)。 std::remove
,以相等为条件选择要删除的元素。
您需要使用std::remove
来代替std::remove_if
和谓词使用std::isnan
。