float f = (float)'a';
if(f < 0){
}
else if(f == 0){
}
else if(f > 0){
}
else{
printf("NaN\n");
}
如果f
是NaN
,则它不会大于/等于/小于0
。
但是如何首先产生这样的f
呢?
我尝试了各种方法来产生NaN
,但都无法成功。
float f = (float)'a';
if(f < 0){
}
else if(f == 0){
}
else if(f > 0){
}
else{
printf("NaN\n");
}
如果f
是NaN
,则它不会大于/等于/小于0
。
但是如何首先产生这样的f
呢?
我尝试了各种方法来产生NaN
,但都无法成功。
使用浮点数,0.0 / 0.0
不是 "除以零" 错误;它会得到 NaN
。
这个 C 程序会打印出 -nan
:
#include <stdio.h>
int main()
{
float x = 0.0 / 0.0;
printf("%f\n", x);
return 0;
}
就NaN在计算机中的表现而言,有两个“无效”数字用于“信令”和“安静”的NaN(类似于保留给正无穷大和负无穷大的两个无效数字)。维基百科条目中有关于NaN如何表示为IEEE浮点数的更多细节。
产生NaN有几种方法:
1)手动生成(通过阅读ieee754
以正确设置位数)
2)使用宏。GCC提供了一个名为NAN
的宏,它在math.h中定义。
检查NaN的通用方法是检查if (f == f)
(对于NaN值应该失败)
对于NaN,浮点表示中的指数位应全部设置为1(浮点由一个带符号位、一组指数位和一组尾数位组成)
isnan()
来检查NaN(需要C99或(在Unix系统上)适当的特性标志,详见manpage)。 - bdonlanNAN
并不来自GCC,而是来自C库。例如,可以查看GNU libc的.../bits/nan.h
文件(由@DarenW提到);但是,当通过预处理器测试检测到时,宏定义是特定于GCC的。 - vinc17nan
和 inf
都是正确的。 - Matt您可以使用NAN
宏,或者直接使用nan / nanf
函数将NaN值赋给变量。
如果要检查是否处理了NaN值,则可以使用isnan()
函数。
以下是一个例子:
#include <stdio.h>
#include <math.h>
int main(void) {
float a = NAN;//using the macro in math.h
float f = nanf("");//using the function version
double d = nan("");//same as above but for doubles!
printf("a = %f\nf = %f\nd = %f\n",a,f,d);
if(isnan(a))
puts("a is a not a number!(NAN)\n");
return 0;
}
运行上面的代码片段会得到以下输出:
a = nan
f = nan
d = nan
a is a not a number!(NAN)
自行运行代码: http://ideone.com/WWZBl8
阅读更多信息:http://www.cplusplus.com/reference/cmath/NAN/
nan
和nanf
不是标准的C函数。 - skykingnan
和 nanf
函数已成为标准的 ISO C 函数。 - MarkWestonmath.h
定义了一些宏,允许您将变量显式设置为无穷大或NaN。由于这是C99的一部分,您可以在其他符合c99标准的编译器中使用以下宏。NAN
宏不是GNU扩展(至少不再是)。它已经被引入到ISO C99标准中。因此,不需要定义_GNU_SOURCE
,只需在某种形式的C99模式或更高版本(而不是C89)下编译即可。 - vinc17#include <math.h>
并使用NAN
宏(如果已定义)。例如,对于GCC,它是通过内置函数实现的:(__builtin_nanf(""))
。<math.h>
头文件)或当NAN
宏未定义时(即使支持NaN,也可能发生),可以通过浮点运算生成NaN,例如0.0 / 0.0
。但是,这可能会有几个问题。static double my_nan = 0.0 / 0.0;
另一个问题是Microsoft Visual C++(至少某些版本)试图在编译时计算0.0 / 0.0
,即使此表达式在代码的任意位置,也会抱怨其有效性。所以,这里的解决方案是相反的:确保编译器不会在编译时对其进行评估,方法是执行以下操作:
static double zero = 0.0;
zero / zero
。由于这些解决方案冲突,可以在特定的宏上测试编译器的预处理器指令(#if
...)。unsigned char
的联合或数组和指针转换就可以得到浮点类型。不要使用整数和其地址的指针转换来进行类型游戏,因为这将违反C别名规则。将浮点变量的所有32位设置为1也可以产生-nan
,如下所示:
float nan_val = 0xffffffff;
-nan
。if (nan_val != nan_val) {
// executes iff nan_val is -nan
}
这种比较方法适用于使用IEEE浮点数的编译器。
const unsigned maxU = ~0;
const float qNan = *((float*)&maxU);
#include <stdio.h>
#include <tchar.h>
#include "math.h"
int _tmain(int argc, _TCHAR* argv[])
{
double dSQRTValue = sqrt( -1.00 );
double dResult = -dSQRTValue; // This statement will result in a NaN.
printf( "\n %lf", dResult );
return 0;
}
1.#QNAN0
sqrt( -1.00 );这在一些机器上会出错。 - rsaxvc
当我们的程序包含像0.0/0.0或sqrt(-1)这样的值时,就会产生NaN错误。