检查数字是+ -Inf还是NaN

时间:2016-03-22 09:25:46

标签: c

出于鲁棒性原因,我想检查浮点数是IEEE-754 + -Inf还是IEEE-754 Nan。我的代码如下,我想知道它是否正确:

 #define PLUS_INFINITE          (1.0f/0.0f)
 #define MINUS_INFINITE         (-1.0f/0.0f)
 #define NAN                    (0.0f/0.0f)

 float Local_Var;
 /*F is a float numnber.*/
 if((unsigned long)(F) == 0x7f800000ul)
   {
    Local_Var = PLUS_INFINITE;
   }
 elseif((unsigned long)(F) == 0xff800000ul)
   {
    Local_Var = MINUS_INFINITE;
   }
   /*fraction = anything except all 0 bits (since all 0 bits represents infinity).*/
 elseif((((unsigned long)(F) & 0x007ffffful) != 0ul )
         &&((unsigned long)(F) == 0x7f800000ul))
        || 
        (((unsigned long)(F) & 0x807ffffful) != 0ul )
        &&
        ((unsigned long)(F) == 0xff800000ul))
   {
    Local_Var = NAN; 
   }
   else{}

3 个答案:

答案 0 :(得分:10)

C99具有用于浮点数分类的宏:

fpclassify(x)返回以下内容之一:

  • FP_NANx不是数字;
  • FP_INFINITEx为正或负无限;
  • FP_ZEROx为零;
  • FP_SUBNORMALx太小,无法以标准格式或
  • 表示
  • FP_NORMAL:正常的浮点数,即以上都不是。

还有一些快捷方式可以检查其中一个类,如果x是什么,则会返回非零值:

   isfinite(x)
   isnormal(x)
   isnan(x)
   isinf(x)

参数x可以是任何浮点表达式;宏检测参数的类型并适用于floatdouble

编辑:由于您不想使用(或不能使用)<math.h>,您可以使用nan和inf的其他属性对您的数字进行分类:

  • nan将false与所有数字进行比较,包括对自身的数字;
  • inf大于FLT_MAX;
  • -inf小于-FLT_MAX

所以:

#include <stdlib.h>
#include <stdio.h>
#include <float.h>

int main()
{
    float f[] = {
        0.0, 1.0, FLT_MAX, 0.0 / 0.0, 1.0/0.0, -1.0/0.0
    };
    int i;

    for (i = 0; i < 6; i++) {
        float x = f[i];

        int is_nan = (x != x);
        int is_inf = (x < -FLT_MAX || x > FLT_MAX);

        printf("%20g%4d%4d\n", x, is_nan, is_inf);
    }

    return 0;
}

在此解决方案中,如果要使用double,则必须调整限制。

答案 1 :(得分:2)

将漂浮物浇铸成长片就好了。它应该是一个联合或一个类型惩罚的指针。

以下是dietlibc(双打)的一个工作示例:
https://github.com/ensc/dietlibc/blob/master/lib/__isinf.c https://github.com/ensc/dietlibc/blob/master/lib/__isnan.c

Musl有一个较短的fpclassify,以及浮动的适当常量:
http://git.musl-libc.org/cgit/musl/tree/src/math/__fpclassifyf.c

答案 2 :(得分:0)

最好使用@M Oehm answer

fpclassify()个功能

备选方案:

float F;
if (F <= FLT_MAX) {
  if (F >= -FLT_MAX) {
    puts("Finite");
  } else {
    puts("-Infinity");
  }
} else {
  if (F > 0) {
    puts("+Infinity");
  } else {
    puts("NaN");
  }
}

如果代码想要弄乱这些位并假设float采用binary32格式:

assert(sizeof (float) == sizeof (uint32_t));
union {
  float f;
  uint32_t u32;
} x;
x.f = F;

掩码取决于floatuint32_t endian的相对端。它们通常都是一样的。

// Is F one of the 3 special: +inf, -inf, NaN?
if (x.u32 & 0x7F800000 == 0x7F800000) {
  if (x.u32 & 0x007FFFFF) {
    puts("NaN");
  } else if (x.u32 & 0x80000000) {
    puts("-Inf");
  } else {
    puts("+Inf");
  }
}