21

忽略我为什么要这样做,754 IEEE fp 标准没有定义以下行为:

float h = NAN;
printf("%x %d\n", (int)h, (int)h);

Gives: 80000000 -2147483648

基本上,无论我给出什么 NAN 值,它都会输出 80000000(十六进制)或 -2147483648(十进制)。这是否有原因和/或这是正确的行为?如果有,怎么来的?

我给它不同的 NaN 值的方式在这里: 如何手动设置等于 NaN 的浮点数的位值?

所以基本上,是否存在 NaN 的有效负载会影响演员表输出的情况?

谢谢!

4

3 回答 3

16

将浮点数转换为整数的结果对于不在整数变量范围内的值(±1 用于截断)未定义/未指定。

第 6.3.1.4 条:

当实浮点类型的有限值转换为除 以外的整数类型_Bool时,小数部分被丢弃(即,该值被截断为 0)。如果整数部分的值不能用整数类型表示,则行为未定义。

如果实现定义了__STDC_IEC_559__,那么对于从浮点类型到除 之外的整数类型的转换_BOOL

如果浮点值是无穷大或 NaN,或者如果浮点值的整数部分超出整数类型的范围,则引发“无效”浮点异常并且未指定结果值。

(附件 F [规范性文件],第 4 点。)

如果实现没有定义__STDC_IEC_559__,那么所有的赌注都没有。

于 2012-04-28T18:53:32.897 回答
11

这种行为是有原因的,但这不是您通常应该依赖的。

正如您所注意到的,IEEE-754 没有指定将浮点 NaN 转换为整数时会发生什么,除了它应该引发一个无效的操作异常,您的编译器可能会忽略它。C标准说行为是未定义的,这意味着你不仅不知道你会得到什么整数结果,你根本不知道你的程序会做什么;该标准允许程序中止或获得疯狂的结果或做任何事情。您可能在 Intel 处理器上执行了该程序,并且您的编译器可能使用内置指令之一进行了转换。英特尔非常仔细地指定指令行为,将浮点 NaN 转换为 32 位整数的行为是返回 0x80000000,而不管 NaN 的有效负载如何,这是您观察到的。

因为 Intel 指定了指令行为,所以如果您知道使用的指令,就可以依赖它。但是,由于编译器不向您提供此类保证,因此您不能依赖正在使用的这条指令。

于 2012-05-01T15:37:40.090 回答
3

首先,根据 IEEE 标准,NAN 是不被视为浮点数的所有内容。所以它可以是几件事。在我使用的编译器中有 NAN 和 -NAN,所以它不仅仅是一个值。

其次,每个编译器都有自己isnan的函数集来测试这种情况,因此程序员不必自己处理这些位。总而言之,我认为偷看价值没有任何区别。您可能会窥视其 IEEE 构造的值,例如符号、尾数和指数,但是,同样,每个编译器都提供了自己的函数(或者更好的说法是库)来处理它。

不过,关于你的测试,我确实有更多话要说。

float h = NAN;
printf("%x %d\n", (int)h, (int)h);

您所做的转换将浮点数转换为整数。如果要获取浮点数表示的整数,请执行以下操作

printf("%x %d\n", *(int *)&h, *(int *)&h);

也就是说,你取浮点数的地址,然后将其作为指向 int 的指针引用,最终取 int 值。这样就保留了位表示。

于 2012-04-28T18:58:25.393 回答