C 如何手动设置等于NaN的浮点的位值?
我正在尝试运行一些测试,将浮点转换为其他类型,并将浮点变量设置为nan的不同值 “IEEE浮点标准单精度(32位)NaN的一个逐位示例是:s111 1111 1axx xxxx xxxx xxxx xxxx xxxx其中s是符号(在应用程序中最常被忽略),a确定NaN的类型,x是额外的有效负载(在应用程序中最常被忽略).如果a=1,则为安静NaN;如果a为零且有效负载为非零,则为信令NaN“C 如何手动设置等于NaN的浮点的位值?,c,floating-point,nan,C,Floating Point,Nan,我正在尝试运行一些测试,将浮点转换为其他类型,并将浮点变量设置为nan的不同值 “IEEE浮点标准单精度(32位)NaN的一个逐位示例是:s111 1111 1axx xxxx xxxx xxxx xxxx xxxx其中s是符号(在应用程序中最常被忽略),a确定NaN的类型,x是额外的有效负载(在应用程序中最常被忽略).如果a=1,则为安静NaN;如果a为零且有效负载为非零,则为信令NaN“ 基本上,我想找到一种方法来设置表示的有效负载或xxxx。在c语言中有什么方法可以做到这一点吗?您可以通过
基本上,我想找到一种方法来设置表示的有效负载或xxxx。在c语言中有什么方法可以做到这一点吗?您可以通过将适当的字符串传递给C99函数来控制“有效负载”位,但这些函数只会生成安静的NaN,并且字符串的解释未指定(大多数实现将其视为十六进制数) 或者,使用工会:
#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;
}
#ifndef_uustdc_uiec_559__
#错误“此程序需要IEEE浮点运算”
#恩迪夫
#包括
#包括
静态断言(sizeof(float)=sizeof(uint32\t),
“此程序要求浮点值精确为32位”);
带有效载荷位的浮点nanf(uint32有效载荷)
{
if(有效负载&0x7FA00000)中止();
单联{
浮动f;
uint32_t i;
}南;
nan.i=0x7FA00000 |有效载荷;
返回nan.f;
}
当两种类型的大小完全相同时,向联合的一个成员写入数据,然后从另一个成员读取数据,不会导致C99+勘误表中出现未定义的行为。(它是C89中未定义的行为,但大多数编译器定义它来做您所期望的。它可能仍然是C++中未定义的行为,我不确定;然而,大多数编译器也定义它来做您所期望的。)
如果使用此函数创建信令NAN,请注意C99/C11附录F中明确未定义其行为
不要试图将union的i
组件分解为具有位字段的结构。结构中位字段的内存布局部分由实现定义,部分未指定,尤其是位字段序列不一定按照与CPU端性相同的顺序打包到字中(或者,实际上,完全正确打包)
标准引用(所有C99):
- 这种联合的使用只是未指明的行为:6.2.6.1p7;J.1
- 结构中的位字段布局不可预测:6.2.6.1p1,2;6.7.2.1p10,11,13;J.3.9
- 信号NAN的行为未定义:F.2.1
- 使用
memcpy
:
int32_t i = 0x7FC00000;
float f;
memcpy(&f, &i, sizeof(f));
您还可以断言
sizeof(f)==sizeof(i)
,但是如果您知道浮点是IEEE,那么您大概也知道基本类型的大小。有一种受支持的方法可以用C编写安静NaN的负载
nan、nanf和nanl函数(属于1999 C规范第7.12.11.2节的math.h头)接受字符串作为参数。strtof、strtod和strtold函数(属于stdlib.h头,第7.20.1.3节)接受格式为“NAN(字符序列)”的字符串。fscanf和sscanf功能遵循strtod。但是,字符序列是以实现定义的方式解释的。(这意味着您的编译器应该向您提供指定解释的文档。某些编译器将不遵守本标准的这一要求。)
fprintf函数(stdio.h,第7.19.6.1节)可以输出形式为“NAN(字符序列)”的字符串,其格式为浮点格式(a、e、f、g),如printf和sprintf。该标准允许不带字符序列的“NAN”输出,因此这在许多编译器中不起作用
因为解释是实现定义的,所以您不应该期望它们是可移植的。它们通常用于调试等特殊目的。你所说的endianness疯狂到底是什么意思?我可能有一个与此相关的问题。简短的版本是,
struct
中的位字段顺序不一定与其他任何内容一致。然而,在所有现代系统上,uint32_t
中的位顺序将与float
中的位顺序相同(过去有一些不同的计算机,但在相当长的一段时间内还没有制造出来)。长版本对于这个盒子来说太长了。我得看看导致你说更多问题的代码。建议你提出一个新问题,并链接到这里。只需链接它:谢谢!