我正在尝试使用转换和浮点数转换为其他类型运行一些测试,我想将我的浮点变量设置为不同的nan值。
“IEEE浮点标准单精度(32位)NaN的一个逐步示例是:s111 1111 1axx xxxx xxxx xxxx xxxx xxxx其中s是符号(在应用程序中最常被忽略),a确定NaN的类型,x是一个额外的有效载荷(通常在应用程序中被忽略)。如果a = 1,它是一个安静的NaN;如果a是零且有效载荷是非零的,那么它是一个信令NaN“
基本上我想找到一种方法来设置表示的有效载荷或xxxx。有没有办法在c中做到这一点?
答案 0 :(得分:8)
您可以通过将适当的字符串传递给C99 nan
, nanf
, nanl
函数来控制“有效负载”位,但这些只会生成 quiet NaN,并且字符串的解释是未指定(大多数实现将其视为十六进制数)。
或者,使用union:
#ifndef __STDC_IEC_559__
#error "This program requires IEEE floating point arithmetic"
#endif
#include <stdint.h>
#include <assert.h>
static_assert(sizeof(float) == sizeof(uint32_t),
"This program requires float to be 32 bits exactly");
float nanf_with_payload_bits(uint32_t payload)
{
if (payload & 0x7FA00000) abort();
union ieee_single {
float f;
uint32_t i;
} nan;
nan.i = 0x7FA00000 | payload;
return nan.f;
}
写入联合的一个成员然后从另一个成员读取,当两个类型的大小完全相同时,不会在C99 +勘误表中引发未定义的行为。 (在C89中是未定义的行为,但是大多数编译器将它定义为你所期望的。它可能仍然是C ++中未定义的行为,我不确定;但是,大多数编译器再次定义它做你期望的事。)
如果您使用此功能创建信令 NaN,请注意它们的行为在C99 / C11附件F中明确未定义。
请勿尝试将联合的i
组件分解为具有位字段的结构。结构中位字段的存储器布局部分是实现定义的并且部分未指定,特别是一系列位字段不必须以与CPU字节顺序相同的顺序打包到字中。 (或者,实际上,根本没有妥善包装)。
标准引用(所有C99):
答案 1 :(得分:3)
使用memcpy
:
int32_t i = 0x7FC00000;
float f;
memcpy(&f, &i, sizeof(f));
你也可以声明sizeof(f) == sizeof(i)
,但如果你知道浮点数是IEEE,那么你可能也知道基本类型的大小。
答案 2 :(得分:3)
支持在C中写入安静NaN的有效负载的方法。
nan,nanf和nanl函数(math.h标题,1999 C规范的7.12.11.2节)接受字符串作为参数。 strtof,strtod和strtold函数(stdlib.h头文件,第7.20.1.3节)接受“NAN(字符序列)”形式的字符串。 fscanf和sscanf函数遵循strtod。但是,字符序列以实现定义的方式解释。 (这意味着您的编译器应该为您提供指定解释的文档。某些编译器将不遵守标准的此要求。)
fprintf函数(stdio.h,第7.19.6.1节)可以输出带有浮点格式(a,e,f,g)的“NAN(字符序列)”形式的字符串,如printf和sprintf的。该标准允许输出“NAN”而没有字符序列,因此这对许多编译器都不起作用。
由于解释是实现定义的,因此您不应期望它们是可移植的。它们通常用于特殊目的,例如调试。