C 如何手动设置等于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语言中有什么方法可以做到这一点吗?您可以通过

我正在尝试运行一些测试,将浮点转换为其他类型,并将浮点变量设置为nan的不同值

“IEEE浮点标准单精度(32位)NaN的一个逐位示例是:s111 1111 1axx xxxx xxxx xxxx xxxx xxxx其中s是符号(在应用程序中最常被忽略),a确定NaN的类型,x是额外的有效负载(在应用程序中最常被忽略).如果a=1,则为安静NaN;如果a为零且有效负载为非零,则为信令NaN“


基本上,我想找到一种方法来设置表示的有效负载或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
      中的位顺序相同(过去有一些不同的计算机,但在相当长的一段时间内还没有制造出来)。长版本对于这个盒子来说太长了。我得看看导致你说更多问题的代码。建议你提出一个新问题,并链接到这里。只需链接它:谢谢!