• Forums
• Posts
Latest Posts
Active Posts
Recently Visited
Search Results
• Page Extras
• Forum Themes

### Hot!Detecting float NaN and Infinity

Page: 12 > Showing page 1 of 2
Author
GoEk
Senior Member
• Total Posts : 98
• Reward points : 0
• Joined: 2012/09/27 00:32:28
• Location: Sweden
• Status: offline
0

# Detecting float NaN and Infinity

Hi,
is there a way in XC16 to detect if a float contains a "real" number (do not mean complex math) and not NaN or Inifinity?

andersm
Super Member
• Total Posts : 2381
• Reward points : 0
• Joined: 2012/10/07 14:57:44
• Location: 0
• Status: online
Re: Detecting float NaN and Infinity 2017/10/06 07:20:48 (permalink)
+2 (2)
C99 added the isnan() and isinf() functions, but I don't know if XC16 supports them. NaN can be tested by comparing the value against itself (they are defined to not be equal any values).
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity 2017/10/06 07:28:46 (permalink)
+2 (2)
Positive infinity is larger than all values except itself and NaN, and negative infinity is smaller than all values except itself and NaN.

NaN is unordered; i.e. it is not equal to, greater than, or less than anything, including itself. The comparison x == x is false if the value of x is NaN. So, you can use this to test whether a value is NaN or not, but the recommended way to test for NaN is with the isnan() function.
GoEk
Senior Member
• Total Posts : 98
• Reward points : 0
• Joined: 2012/09/27 00:32:28
• Location: Sweden
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 07:57:22 (permalink)
0
Thanks all. I've tried the X == X method but that does not catch Infinity.

What I need is a is_real(floatvalue) and I 've used this:

`bool is_real(float d){return (d || d==0);}`

Apparently converting a non-real float to bool will always be false.
post edited by GoEk - 2017/10/06 08:09:22
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity 2017/10/06 08:00:08 (permalink)
+1 (1)
It looks like XC16 does not have the INFINITY macro (from ISO C99 standard), but there is a HUGH_VAL macro in its <math.h> file
`#define HUGE_VAL (__DBL_MAX__ * 2.0)`

which can be used to check for overflow.
du00000001
Just Some Member
• Total Posts : 1891
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: offline
Re: Detecting float NaN and Infinity 2017/10/06 08:08:35 (permalink)
+1 (1)
I'd check for the bit pattern(s) - expecting 0xFFFFFF(FF) and eventually a small number of other patterns to represent NaN.
Maybe I expect too much but this should be documented somewhere (compiler manual or some header file.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity 2017/10/06 08:27:05 (permalink)
+3 (3)
`//// returns 1 if positive infinity, -1 if negative infinity, 0 otherwise.//intisinf(float f){    long l;    l = *((long *)&f);    if (l == 0x7F800000)        return 1;    if (l == 0xFF800000)        return -1;    return 0;}`

post edited by 1and0 - 2017/10/06 09:06:41
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 09:42:21 (permalink)
+2 (2)
Goran Ekstrom
What I need is a is_real(floatvalue) ...

Try this:
`//// returns 1 if real, 0 otherwise//intisreal(float f){    long l;    l = *(long *)&f;    if (l == 0x7F800000) // +inf        return 0;    if (l == 0xFF800000) // -inf        return 0;    if (l == 0x7FFFFFFF) // NaN        return 0;     return 1;}`

Chris A
Super Member
• Total Posts : 785
• Reward points : 0
• Joined: 2010/07/20 04:37:07
• Location: 0
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 11:14:59 (permalink)
+1 (1)
I always used similar to 1and0 solution.
This was some years back on pc with Microsoft compiler which would throw an exception if you tried to access the value in a floating point comparison so you had to test by casting into a long with * (long *) &f
simong123
Lab Member No. 003
• Total Posts : 1242
• Reward points : 0
• Joined: 2012/02/07 18:21:03
• Location: Future Gadget Lab (UK Branch)
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 11:39:12 (permalink)
+1 (1)
1and0
Goran Ekstrom
What I need is a is_real(floatvalue) ...

Try this:
`//// returns 1 if real, 0 otherwise//intisreal(float f){    long l;    l = *(long *)&f;    if (l == 0x7F800000) // +inf        return 0;    if (l == 0xFF800000) // -inf        return 0;    if (l == 0x7FFFFFFF) // NaN        return 0;     return 1;}`

Unfortunately this is incorrect. There are many NaN's (sign =0 or 1,exp = all ones, fraction !=0).
Try
`//// returns 1 if real, 0 otherwise//intisreal(float f){    long l;    l = *(long *)&f;    if (l == 0x7F800000) // +inf        return 0;    if (l == 0xFF800000) // -inf        return 0;    if ((l & 0x7F800000)==0x7F800000) // NaN (valid because +/-Inf already tested for) (or use f!=f)        return 0;     return 1;}`

du00000001
Just Some Member
• Total Posts : 1891
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 13:03:54 (permalink)
+1 (1)
Honestly - who cares for details? Cut things short!
`bool is_real(float f){    if ( (*(long*)&f & 0x7F800000) == 0x7F800000) return false;    return true;}`
Could cut this even down to (unsigned) short if the memory scheme (big vs. little endian) is considered.
post edited by du00000001 - 2017/10/06 13:06:46

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
simong123
Lab Member No. 003
• Total Posts : 1242
• Reward points : 0
• Joined: 2012/02/07 18:21:03
• Location: Future Gadget Lab (UK Branch)
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 13:12:43 (permalink)
+2 (2)
Hah - Doh!
Yep.
`if ( (*((unsigned*)&f+1) & 0x7f80u) == 0x7f80u) return false;`

should do it (for XC16).
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 13:21:55 (permalink)
+1 (1)
simong123
There are many NaN's (sign =0 or 1,exp = all ones, fraction !=0).

I figured there would be. I found that NaN from evaluating 0.0/0.0 and sqrt(-1). Agreed on using just one if() statement to compare isreal() or not.
dan1138
Super Member
• Total Posts : 2745
• Reward points : 0
• Joined: 2007/02/21 23:04:16
• Location: 0
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 13:49:57 (permalink)
+2 (2)
While this thread uses methods that cast a floating point data type to an integer data type there are some portability issues that may need some consideration.

The suggested solutions seem to assume that only the IEEE-754 floating point format of 32-bits is in use on the XC16 compiler.

While this most often the case some of the Microchip compilers support a 24-bit floating point format.

I do not know for sure but the byte ordering of a float in the XC8 compiler for PIC16F and PIC18F targets seems to be Least Significant Byte first. This mean that the offset to the high 16 bits of a float may be either 1 or 2 bytes depending on which floating point format was selected for the XC8 compiler.

It is unlikely that users of this forum will encounter something other than the IEEE-754 floating point format but you should be aware that other representations may occur such as 64-bit binary or even BCD using 4 bits per decimal digit.

<Edit> Correct my confusion regarding floating point support in the XC16 compiler and change XC16 to XC8 in my example of a Microchip XC compiler that offers a different floating point format.

post edited by dan1138 - 2017/10/06 15:58:42
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 13:56:06 (permalink)
0
dan1138
The suggested solutions seem to assume that only the IEEE-754 floating point format of 32-bits is in use on the XC16 compiler. While this is most often the case the compiler does support (sort of) a 24-bit floating point format.

I do not know for sure but the byte ordering of a float in the XC16 compiler for PIC16F and PIC18F targets seems to be Least Significant Byte first. This mean that the offset to the high 16 bits of a float may be either 1 or 2 bytes depending on which floating point format was selected for the XC16 compiler.

I'm not aware XC16 supports 24-bit floating point data types.  PIC16F and 18F use the XC8 compiler.  As I understand it, both XC8 and XC16 compilers use the IEEE-754 format.

du00000001
Just Some Member
• Total Posts : 1891
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 13:58:54 (permalink)
+1 (1)
@ dan1138
I'm very aware of portability issues, but they can be overcome by more intricate coding.

And I'm absolutely sure that XC16 does not create any code for PIC16 or PIC18.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
GoEk
Senior Member
• Total Posts : 98
• Reward points : 0
• Joined: 2012/09/27 00:32:28
• Location: Sweden
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 14:11:46 (permalink)
0
To explain it even further I have an Analog Devices SHARK DSP that I communicate with using a UART port. For the moment the DSP occasionally screws up and sends me garbage 32 bit float values so I need to determine if *any* random 32 bit pattern can be considered a "real" float value. Hence simply detecting the constants +-Infinity and NaN is not enough.
du00000001
Just Some Member
• Total Posts : 1891
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 14:17:32 (permalink)
0
Most bit patterns will represent a valid float value. Beyond the small number of NaN patterns there is no way to distinguish "sense" and "nonsense" based on the bit pattern. Imagine the 32-Bit integers: every pattern is valid - whether considered good or "scrap".

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
GoEk
Senior Member
• Total Posts : 98
• Reward points : 0
• Joined: 2012/09/27 00:32:28
• Location: Sweden
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 14:23:01 (permalink)
+1 (1)
du00000001
Most bit patterns will represent a valid float value. Beyond the small number of NaN patterns there is no way to distinguish "sense" and "nonsense" based on the bit pattern. Imagine the 32-Bit integers: every pattern is valid - whether considered good or "scrap".

Yes and after the first line of "defence" to detect truly garbage float there will also be a range check. Then I have done all I can do.
1and0
Access is Denied
• Total Posts : 8001
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: Detecting float NaN and Infinity (i.e. a real value) 2017/10/06 14:45:27 (permalink)
+3 (3)
Goran Ekstrom
To explain it even further I have an Analog Devices SHARK DSP that I communicate with using a UART port. For the moment the DSP occasionally screws up and sends me garbage 32 bit float values so I need to determine if *any* random 32 bit pattern can be considered a "real" float value. Hence simply detecting the constants +-Infinity and NaN is not enough.

You need to find out why the DSP send garbage and fix it.
Page: 12 > Showing page 1 of 2