我想知道以下类型的nan之间有什么区别。除了NAN_macro的视觉差异(它的计算结果为-nan(ind),而不是nan)之外,它们的行为似乎都是一样的(如下面的示例脚本所示)。
我看了一下其他一些答案,例如安静的NaN和信号NaN有什么区别?。但我仍然不太明白为什么NAN是-nan(ind),而std::numeric_limits<double>::quiet_NaN()是nan,或者为什么我们有std::nan("")和std::nan("1"),如果最终它们看起来都是相同的概念。
任何解释或澄清联系将是很好的。
#include <cmath>
#include <limits>
int main()
{
using num_lim = std::numeric_limits<double>;
const double NAN_macro = static_cast<double>(NAN); // -nan(ind)
const double NAN_quiet = num_lim::quiet_NaN(); // nan
const double NAN_sig = num_lim::signaling_NaN(); // nan
const double NAN_str = std::nan(""); // nan
const double NAN_str1 = std::nan("1"); // nan
const double NAN_strLong = std::nan("some string"); // nan
const bool isnan_macro = std::isnan(NAN_macro); // true
const bool isnan_quiet = std::isnan(NAN_quiet); // true
const bool isnan_sig = std::isnan(NAN_sig); // true
const bool isnan_str = std::isnan(NAN_str); // true
const bool isnan_str1 = std::isnan(NAN_str1); // true
const bool isnan_strLong = std::isnan(NAN_strLong); // true
const bool not_equal_macro = (NAN_macro != NAN_macro); // true
const bool not_equal_quiet = (NAN_quiet != NAN_quiet); // true
const bool not_equal_sig = (NAN_sig != NAN_sig); // true
const bool not_equal_str = (NAN_str != NAN_str); // true
const bool not_equal_str1 = (NAN_str1 != NAN_str1); // true
const bool not_equal_strLong = (NAN_strLong != NAN_strLong); // true
const double sum_macro = 123.456 + NAN_macro; // -nan(ind)
const double sum_quiet = 123.456 + NAN_quiet; // nan
const double sum_sig = 123.456 + NAN_sig; // nan
const double sum_str = 123.456 + NAN_str; // nan
const double sum_str1 = 123.456 + NAN_str1; // nan
const double sum_strLong = 123.456 + NAN_strLong; // nan
}发布于 2020-04-20 19:49:54
IEEE 754用比特模式表示NaN,其指数为所有1s和非零分数(请注意,所有浮点十进制值都由“符号”、“指数”和“分数”表示),然后,您可以表示许多不同的NaN,因为“非零分数”可能有很多不同的值。
要突出显示您的NaN表示,请使用以下内容扩展代码:
#include <cmath>
#include <limits>
#include <bitset>
#include <iostream>
union udouble {
double d;
unsigned long long u;
};
void Display(double doubleValue, char* what)
{
udouble ud;
ud.d = doubleValue;
std::bitset<sizeof(double) * 8> b(ud.u);
std::cout << "BitSet : " << b.to_string() << " for " << what << std::endl;
}
int main()
{
using num_lim = std::numeric_limits<double>;
const double NAN_macro = static_cast<double>(NAN); // -nan(ind)
const double NAN_quiet = num_lim::quiet_NaN(); // nan
const double NAN_sig = num_lim::signaling_NaN(); // nan
const double NAN_str = std::nan(""); // nan
const double NAN_str1 = std::nan("1"); // nan
const double NAN_strLong = std::nan("some string"); // nan
...
Display( NAN_macro, "NAN_macro" );
Display( NAN_quiet, "NAN_quiet" );
Display( NAN_sig, "NAN_sig" );
Display( NAN_str, "NAN_str" );
Display( NAN_str1, "NAN_str1" );
Display( NAN_strLong, "NAN_strLong" );
}即使它有一些UB (可以修复,请参阅Ruslan注释),它确实可以说明我在下面解释的内容),这个程序输出:
BitSet : 0111111111111000000000000000000000000000000000000000000000000000 for NAN_macro
BitSet : 0111111111111000000000000000000000000000000000000000000000000000 for NAN_quiet
BitSet : 0111111111110100000000000000000000000000000000000000000000000000 for NAN_sig
BitSet : 0111111111111000000000000000000000000000000000000000000000000000 for NAN_str
BitSet : 0111111111111000000000000000000000000000000000000000000000000001 for NAN_str1
BitSet : 0111111111111000000000000000000000000000000000000000000000000000 for NAN_strLong他们都有:
NAN宏的定义可能有所不同,我怀疑这是C++标准的一部分。实际上,这个“分数”或“有效载荷”(请参阅Ruslan注释)值可以用来存储您想要存储的任何信息(比如“为什么这里有一个nan”?),这个值叫做南拳。
这就是为什么您可能在某个点上有“不同的”NaN值(非数、非数或您创建的任何NaN都符合IEEE 754...even,如果有不同的内存表示,这些值都是NaN值(x!=x和std::isnan(x)==true) )。
所以,回答你的问题:
为什么NAN是
-nan(ind)而std::numeric_limits<double>::quiet_NaN()是nan
因为您的编译器像这样定义了NAN宏,所以使用另一个编译器可能会有所不同。顺便说一句,它就像min/max宏,即使您有定义它们的错误想法,不要使用它们,更喜欢std函数,因为它们是标准的一部分,所以应该与您使用的任何编译器一样工作。
为什么我们有
std::nan("")和std::nan("1"),如果在一天结束时,它们似乎都是相同的概念。
也许“帮助你玩南拳”是一个答案,即使我怀疑这些功能是为了这个特定的目的而创建的。正确的答案可能只是“如果您需要与NaN和std::signaling_NaN不同的东西,请让您决定要用于您的std::quiet_NaN和std::signaling_NaN的”分数“值”。
资料来源:https://steve.hollasch.net/cgindex/coding/ieeefloat.html
还使用https://stackoverflow.com/a/40737266/3336423输出NaN内存表示。
https://stackoverflow.com/questions/61253965
复制相似问题