huk*_*ing 6 c floating-point c99 nan c89
isnan(), isinf()
直到 C99 才出现在规范中,无论如何在 C89 中实现这样的功能?
我可以if (d * 0 != 0)
用来检查 d 是 NaN 还是 Inf,但我们总是使用选项编译我们的项目,该选项-Werror=float-equal
想大喊:error: no == or != on float point value
那么人们如何在 C89 中检查 nan 和 inf 呢?
自 C99
isinf(x)
并isnan(x)
处理 的实浮点类型x
和 对于其他类型(如 )未定义int
。 isinf(x)
并且isnan(x)
是宏。
isinf(x)
并isnan(x)
使用相同的名称float, double, long double
,因此就像一个重载的函数。
信息
对于 C89,我们可以使用单独的函数来测试_MAX
. 请注意,C89 没有定义long double
.
“自己动手”isinf()
可以使用以下内容。
#include <float.h>
int isinf_f(float x) { return x < -FLT_MAX || x > FLT_MAX; }
int isinf_d(double x) { return x < -DBL_MAX || x > DBL_MAX; }
Run Code Online (Sandbox Code Playgroud)
请注意,C 不要求实现支持无穷大。如果是这样,上述内容永远不会正确。
伊斯南
C89 的“自己动手”isnan()
更棘手。可以在下面作为函数或简单的宏来完成。功能依赖于现代的 Not-a-number 行为,其中 Nan 永远不等于任何东西,甚至不等于它本身。将是不通过C89规定,但一般底层浮点系统遵循这一点。否则,您需要更特定于平台的方法。
/* Note `x` used twice here - so use with caution */
#define my_is_nan(x) ( (x) != (x) )
int isnan_f(float x) { x != x; }
int isnan_d(double x) { x != x; }
Run Code Online (Sandbox Code Playgroud)
请注意,C 不要求实现支持Not-a-number。如果是这样,上述内容永远不会正确。
鉴于 C89 狂野西部时代,我不会假设符合 IEEE 754。 Infinity和NAN正是缺乏正式合规性的任何浮点实现的边缘。祝你好运。
C 允许使用更广泛的 FP 数学,具体取决于FLT_EVAL_METHOD
因此1.0f / 7.0f
可能使用double
. 这使事情有点复杂,但使用真正的函数确实将x
表达式强制转换为所需的类型。
如果您的系统使用IEEE 754 标准来表示浮点值(大多数系统都是这样做的),那么您可以显式检查NaN
和inf
值。单精度(32 位)浮点值具有1
符号位(位 31)、8 bit
指数(位 30-23)和23 bit
尾数(位 22-0),布局如下(二进制格式):
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
Run Code Online (Sandbox Code Playgroud)
无穷大值用全 1 的指数和全 0 的尾数表示(符号位区分负无穷大和正无穷大)。
NaN值由全 1 和非零分数的指数表示(安静的 NaN具有最高有效的尾数位设置,而信号 Nan则清除该位)。
因此,通过“转换”float
为无符号 32 位整数,我们可以显式检查这些表示形式(假设unsigned int
是 32 位类型):
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
Run Code Online (Sandbox Code Playgroud)
双精度值的表示类似,但具有11
指数位 (62-52) 和52
尾数位 (51-0)。