I would like to try to expose NaN by a logical consideration.
If a float
is not infinite (neither greater than FLT_MAX
nor less than -FLT_MAX
), it should therefore be less than or equal to FLT_MAX
. If not, it is NaN.
int is_inf(float x) { return x < -FLT_MAX || x > FLT_MAX; }
int is_nan(float x) { return !is_inf(x) && !(x <= FLT_MAX); }
My very first answer and already down voted. So I decided to add an example. Well, it works as expected.
#include <stdio.h>
#include <math.h>
#include <float.h>
static int is_inf(float x) { return x < -FLT_MAX || x > FLT_MAX; }
static int is_nan(float x) { return !is_inf(x) && !(x <= FLT_MAX); }
static void show(float f)
{
float g = -f;
printf("% f : %i %i %i %i\n", f, isinf(f), isnan(f), is_inf(f), is_nan(f));
printf("% f : %i %i %i %i\n", g, isinf(g), isnan(g), is_inf(g), is_nan(g));
}
int main(void)
{
float inf = FLT_MAX * 2.0f;
float nan = inf / inf;
show(inf);
show(nan);
show(FLT_MAX);
show(FLT_MIN);
show(0.0f);
show(1234.5678f);
return 0;
}
Compiled and started under Linux:
$ gcc infnan.c
$ ./a.out
inf : 1 0 1 0
-inf : -1 0 1 0
-nan : 0 1 0 1
nan : 0 1 0 1
340282346638528859811704183484516925440.000000 : 0 0 0 0
-340282346638528859811704183484516925440.000000 : 0 0 0 0
0.000000 : 0 0 0 0
-0.000000 : 0 0 0 0
0.000000 : 0 0 0 0
-0.000000 : 0 0 0 0
1234.567749 : 0 0 0 0
-1234.567749 : 0 0 0 0
Complementary solution for the data type double
with improved return value.
static int is_inf(double x) {
if (x > DBL_MAX) return 1;
if (x < -DBL_MAX) return -1;
return 0;
}
static int is_nan(double x) { return !is_inf(x) && !(x <= DBL_MAX); }
Thinking about it again, is_nan
could be calculated easier.
int is_nan(double x) { return !(x > DBL_MAX || x <= DBL_MAX); }
Or even without an included constant.
int is_nan(double x) { return !(x > 0.0 || x <= 0.0); }
x > DBL_MAX
for infinity andx != x
for NAN. – Catlee-Werror=float-equal
. – Hilbert-Werror=float-equal
, simple disable that warning for that section of code. How to disable GCC warnings for a few lines of code. – Catlee#pragma directive
would work. – Hilbert