如何手动设置等于NaN的float的位值?

Chr*_*ris 4 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中这样做?

zwo*_*wol 8

您可以通过传递适当的串到C99,以控制"有效载荷"位nan,nanf,nanl功能,但是这些只会产生安静的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;
}
Run Code Online (Sandbox Code Playgroud)

写入联合的一个成员然后从另一个成员读取,当两种类型的大小完全相同时,不会在C99 +勘误表中引发未定义的行为.(这 C89 未定义的行为,但是大多数编译器都将它定义为你所期望的.它可能仍然是C++中未定义的行为,我不确定;但是,大多数编译器再次定义它来做你期望的事情. )

如果您使用此函数创建信令 NaN,请注意它们的行为在C99/C11附录F中明确未定义.

不要试图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


Ste*_*sop 5

使用memcpy

int32_t i = 0x7FC00000;
float f;
memcpy(&f, &i, sizeof(f));
Run Code Online (Sandbox Code Playgroud)

您也可以断言sizeof(f) == sizeof(i),但如果您知道浮点数是 IEEE 的,那么您大概也知道基本类型的大小。