如何从 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
的谓词一起使用。
我有
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
的谓词一起使用。