How to check if a float is infinity/zero/denormal?

6
int is_infinity/is_zero/is_denormal(float f){
    //do something, return 0 or 1
}

This is what I did for checking if a float is negative. I want to do something similar for the other functions, but I'm not sure how.

int is_negative(float val){
    union sp_object copy;
    copy.frep = val;
    if((copy.irep & 0x80000000) != 0)
        return 1;
    else
        return 0;
}
c
floating-point
asked on Stack Overflow Jun 5, 2017 by HOHO • edited Dec 4, 2020 by chux - Reinstate Monica

2 Answers

7

I want to do something similar for the other functions

Avoid bit fields, @David, as it depends on implementation specifics. <math.h> contains macros to classify a float. These macros work for double and long double too.

#include <math.h>

// Adjust returns values as desired.
int is_infinity_is_zero_is_denormal(float f) {
  if (isinf(f)) return 'i';
  if (f == 0.0f) return 'z';
  if (isnan(f)) return 'n';
  if (isnormal(f)) return 0;  // neither zero, subnormal, infinite, nor NaN

  // All that is left is de-normal/sub-normal.
  return 'd';
}

Or maybe simply

bool is_infinity_is_zero_is_denormal(float f) {
  return !(isnormal(f) || isnan(f));
}

Also see int fpclassify(real-floating x); to classify the number in one step.

classifies its argument value as NaN, infinite, normal, subnormal, zero, or into another implementation-defined category. C11 §7.12.3.1 2

The number classification macros FP_INFINITE FP_NAN FP_NORMAL FP_SUBNORMAL FP_ZERO represent the mutually exclusive kinds of floating-point values. They expand to integer constant expressions with distinct values. §7.12 6

bool is_infinity_is_zero_is_denormal(float f) {
  // return fpclassify(f) & (FP_INFINITE | FP_ZERO | FP_SUBNORMAL);  // not good
  switch (fpclassify(f)) {
    case FP_INFINITE:
    case FP_ZERO:
    case FP_SUBNORMAL:
      return true;
  }
  return false;
}

Let the compiler handle the optimization.

answered on Stack Overflow Jun 5, 2017 by chux - Reinstate Monica • edited Jun 20, 2020 by Community
-1

ISO C99 provides an INFINITY and NAN macro that can be compared against. It is recommended to use the functions isfinite(), isnormal(), and isnan(). Note that as EOF points out, comparing against the NAN macro will not determine whether a value is actually NAN.

For C99:

https://www.gnu.org/software/libc/manual/html_node/Floating-Point-Classes.html#Floating-Point-Classes

https://www.gnu.org/software/libc/manual/html_node/Infinity-and-NaN.html

For earlier code you're out of luck:

http://c-faq.com/fp/nan.html

answered on Stack Overflow Jun 5, 2017 by David • edited Jun 5, 2017 by David

User contributions licensed under CC BY-SA 3.0