7
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;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
HOHO
  • 71
  • 1
  • 1
  • 4
  • 3
    [`std::isinf`](http://en.cppreference.com/w/cpp/numeric/math/isinf) etc. Maybe [`std::fpclassify`](http://en.cppreference.com/w/cpp/numeric/math/FP_categories) if you're after all kinds of values. – Kerrek SB Jun 05 '17 at 19:35
  • 1
    @FrançoisAndrieux - Doesn't matter. `fpclassify` is part of the C standard library. – StoryTeller - Unslander Monica Jun 05 '17 at 19:38
  • @StoryTeller `std::fpclassify` isn't though – François Andrieux Jun 05 '17 at 19:39
  • Look at the functions [here](http://en.cppreference.com/w/c/numeric/math). Specifically in the section *Classification and comparison* – NathanOliver Jun 05 '17 at 19:39
  • @FrançoisAndrieux - Comments don't need to be nearly as pedantic, they aren't answers. – StoryTeller - Unslander Monica Jun 05 '17 at 19:39
  • Possible duplicate of [How to use nan and inf in C?](https://stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in-c) – Stargateur Jun 05 '17 at 19:39
  • Can I do them with bit fields packing/unpacking? if yes.. how? – HOHO Jun 05 '17 at 19:40
  • @StoryTeller I didn't want to make a big deal out of this, it's just that OP edited the tags following another of my comments and I was notifying the other comment authors if they wanted to improve their comments. `std::numeric_limits` certain doesn't apply though. – François Andrieux Jun 05 '17 at 19:40
  • http://pubs.opengroup.org/onlinepubs/000095399/functions/isnan.html C99? –  Jun 05 '17 at 19:40
  • 1
    @HOHO You really don't want to get into bit fields if you don't have to. There are easier methods provided for you by C99 – David Jun 05 '17 at 19:43
  • Shouldn't `is_negative(float x)` be just `{ return x < 0.f; }`? – unwind Jun 05 '17 at 20:45
  • @unwind Consider the difference with `x= -0.0f` and then between `is_negative(x)` and `return x < 0.f;` – chux - Reinstate Monica Jun 05 '17 at 21:06
  • I just tried `double d = -0.0; printf("%f\n", d); if (d < 0.0) printf("less\n");` which outputs `-0.000000` but not result of comparison. Never mind `float`, it is in my "yesterday" bin. – Weather Vane Jun 05 '17 at 21:10
  • @HOHO Depending on coding goals, your implementation of `int is_negative(float val)` is a problem with 1) unexpected FP formats relative to `copy.irep` and 2) when `val` is a Not-A-Number. In the second case, some NANs do not clearly consider a NaN with its "sign" bit set to be a _negative_ number. – chux - Reinstate Monica Jun 05 '17 at 21:12
  • @WeatherVane `double d = -0.0; if (d < 0.0) printf("less\n");` _should_ print nothing as `d` is not less than 0.0. -0.0 and +0.0 have the same _value_, yet different signs. – chux - Reinstate Monica Jun 05 '17 at 21:13
  • @chux my point was unwind's comment `return x < 0.f;` but `-0.0;` is negative. – Weather Vane Jun 05 '17 at 21:15
  • @chux Yeah, I guess that's a point although I consider `-0` to make little sense as a negative number. :) – unwind Jun 05 '17 at 21:27
  • @chux my first comment was an unnecessary point - the same as yours by the time I posted it. – Weather Vane Jun 05 '17 at 21:30
  • @unwind True. OP's `is_negative()` is more like a sign bit test than the arithmetic idea of _is_negative_. Latter has ambiguity of definition when `x== -0.0` or `x== -NAN`. – chux - Reinstate Monica Jun 05 '17 at 21:31

2 Answers2

9

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.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Your last example is totally wrong, because the `FP_*` macros are not required to be defined as powers of 2, and actually they are not, at least in GCC and MSVC. It could have tons of false positive or not work at all if any macro would be equal to zero (actually `FP_ZERO` is 0 in MSVC). – Giovanni Cerretani May 28 '20 at 13:27
  • @GiovanniCerretani Agreed. Post amended. – chux - Reinstate Monica May 28 '20 at 14:38
-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

David
  • 1,624
  • 11
  • 13
  • 5
    You cannot find out whether a floating-point number is `NAN` by comparing it to `NAN`, because `NAN` compares unequal to all floating-point numbers and `NAN`. – EOF Jun 05 '17 at 19:51