如何在c中生成NaN浮子?
float f = (float)'a'; if(f 0){ } else{ printf("NaN\n"); }
如果它是NaN
则f
不会大于/等于/小于0
。
但是如何在第一时间产生这样的f
?
我尝试了各种方法来生产NaN
,但没有一种方法可行。
使用浮点数, 0.0 / 0.0
不是“除以零”错误; 它导致NaN
。
这个C程序打印-nan
:
#include int main() { float x = 0.0 / 0.0; printf("%f\n", x); return 0; }
就NaN
看起来对计算机而言,两个“无效”数字被保留用于“信令”和“安静”NaN(类似于为正无穷大保留的两个无效数字)。 维基百科条目提供了有关NaN如何表示为IEE浮点数的更多详细信息。
要产生纳米,有几种方法:
1)手动生成(读取ieee754
以正确设置位)
2)使用宏。 GCC公开了一个宏NAN
。 它在math.h中定义
检查nan的一般方法是检查if (f == f)
(对于nan值应该失败)
对于nan,float表示中的指数位应全部设置为1(float由一个有符号位,一组指数位和一组尾数位组成)
从GNU GCC手册中, math.h
定义了允许您将变量显式设置为无穷大或NaN的宏。 由于这是C99的一部分,您可以将以下宏与其他符合c99的编译器一起使用,我希望如此。
– Macro:float INFINITY表示正无穷大的表达式。 它等于1.0 / 0.0等数学运算产生的值。 -INFINITY表示负无穷大。
您可以通过将浮点值与此宏进行比较来测试浮点值是否为无限值。 但是,不建议这样做; 你应该使用isfinite宏代替。 请参阅浮点类。
该宏是在ISO C99标准中引入的。
– Macro:float NAN表示“非数字”值的表达式。 此宏是GNU扩展,仅在支持“非数字”值的计算机上可用 – 也就是说,在所有支持IEEE浮点的计算机上都可用。
您可以使用’#ifdef NAN’来测试机器是否支持NaN。 (当然,您必须安排GNU扩展可见,例如通过定义_GNU_SOURCE,然后您必须包含math.h.)
有关详细信息,请参阅此处: http : //www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html
您可以使用NAN
宏,也可以只使用nan/nanf
函数之一为变量分配nan值。
要检查您是否正在处理nan值,可以使用isnan()
。 这是一个例子:
#include #include 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/
这也适用于常量(0/0将在vs上产生编译器错误):
const unsigned maxU = ~0; const float qNan = *((float*)&maxU);
对于托管C实现,可以执行#include
并使用NAN
宏(如果已定义)。 例如,对于GCC,它由内置实现: (__builtin_nanf (""))
。
对于独立的C实现(
头可能不可用)或未定义NAN
宏(即使可能支持NaN可能会发生),可以生成具有浮点运算的NaN例如0.0 / 0.0
。 但是,它可能存在一些问题。
首先,这样的操作也会生成exception,在某些C实现上可能存在陷阱。 可以确保它在编译时计算:
static double my_nan = 0.0 / 0.0;
另一个问题是Microsoft Visual C ++(至少某些版本)尝试在编译时评估0.0 / 0.0
(即使此表达式在代码中的任意位置)并且抱怨其有效性。 所以,这里的解决方案是相反的:确保编译器不会在编译时评估它,通过执行以下操作:
static double zero = 0.0;
然后使用zero / zero
。 由于这些解决方案存在冲突,因此可以使用特定宏上的预处理程序指令( #if
…)来测试编译器。
也可以选择基于NaN编码的解决方案,但也存在可移植性问题。 首先,IEEE 754标准没有完全定义NaN的编码,特别是区分安静和信令NaN的方式(硬件在实践中有所不同); 信令NaN将产生不确定的行为。 此外,IEEE 754标准没有定义如何在存储器中表示比特串,即可能需要检测字节序。 如果这些问题得到解决,可以使用带有指针强制转换的联合或带unsigned char
数组来获得浮点类型。 不要使用在其地址上强制转换指针的整数来进行类型惩罚,因为这会破坏C别名规则。
以下C程序将产生一个NaN。 第二个陈述将导致NaN。
#include #include #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
当我们编程包含像@Dan Cecile OR sqrt(-1)所述的0.0 / 0.0之类的值时,会生成nan。