我发现检查fetestexcept(FE_INVALID)很有用。然而,仅仅打印值std::numeric_limits<double>::signaling_NaN()(例如,使用std::cout)似乎设置了这个标志,而我只希望在浮点运算中使用NaN时设置该标志。是否可以在不更改FE_INVALID标志的情况下打印?
fetestexcept(FE_INVALID)
std::numeric_limits<double>::signaling_NaN()
std::cout
NaN
FE_INVALID
ryevplcw1#
是的,可以在不触发FE_INVALID标志的情况下打印信令NaN的值。一种方法是使用memcpy函数将信令NaN的位模式复制到所需类型的变量中,而无需实际执行可能引发FE_INVALID标志的浮点运算。下面是一个如何执行此操作的示例:
#include <iostream> #include <cmath> #include <cstring> #include <cfenv> #include <limits> int main() { double snan = std::numeric_limits<double>::signaling_NaN(); double snan_copy; std::memcpy(&snan_copy, &snan, sizeof(double)); std::fesetround(FE_TOWARDZERO); // Set rounding mode to avoid FE_INVALID flag std::cout << snan_copy << std::endl; // Print the signaling NaN std::cout << "FE_INVALID flag is: " << (std::fetestexcept(FE_INVALID) ? "set" : "not set") << std::endl; return 0; }
在这个例子中,我们首先使用std::numeric_limits::signaling_NaN()创建一个信令NaN,然后使用std::memcpy将信令NaN的位模式复制到变量snan_copy中。然后将舍入模式设置为FE_TOWARDZERO,以避免在打印snan_copy的值时触发FE_INVALID标志。最后,我们使用std::fetestexcept检查FE_INVALID标志的状态。请注意,此方法仅适用于信令NaN,它具有特定的位模式,将其与安静NaN区分开来。如果您尝试使用std::memcpy复制安静NaN的位模式,则结果可能根本不是NaN,或者它可能在某些平台上是信令NaN而在其他平台上不是。
1条答案
按热度按时间ryevplcw1#
是的,可以在不触发FE_INVALID标志的情况下打印信令NaN的值。一种方法是使用memcpy函数将信令NaN的位模式复制到所需类型的变量中,而无需实际执行可能引发FE_INVALID标志的浮点运算。
下面是一个如何执行此操作的示例:
在这个例子中,我们首先使用std::numeric_limits::signaling_NaN()创建一个信令NaN,然后使用std::memcpy将信令NaN的位模式复制到变量snan_copy中。然后将舍入模式设置为FE_TOWARDZERO,以避免在打印snan_copy的值时触发FE_INVALID标志。最后,我们使用std::fetestexcept检查FE_INVALID标志的状态。
请注意,此方法仅适用于信令NaN,它具有特定的位模式,将其与安静NaN区分开来。如果您尝试使用std::memcpy复制安静NaN的位模式,则结果可能根本不是NaN,或者它可能在某些平台上是信令NaN而在其他平台上不是。