checking double for Inf or NaN - how?

  • Thread starter =?ISO-8859-1?Q?Martin_J=F8rgensen?=
  • Start date
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Hi,

I found the code below from
http://www.blitzbasic.com/Community/posts.php?topic=55633

------
' Check if number is finite.


Local u:Double = 2 ' also works for floats

For Local n = 1 To 12
Print isfinite(u) + " " + u
u :* u
Next

Print
Print "What about NaN?"
Print

u = u - u
Print isfinite(u) + " " + u


Function isfinite( x:Double ) ' assumes Intel byte order

Const EXP_BITS = %01111111111100000000000000000000

Local bits = ( Int Ptr Varptr x )[1] ' [0] for Mac?

Return ( bits & EXP_BITS ) <> EXP_BITS ' exponent is all 1s for
infinity or NaN

End Function


------

I need something like that - but the author writes that "This is intel
only. Anybody want to make it multiplatform? It shouldn't be difficult,
but I don't have a Mac".

The code above doesn't look like "standard C" to me... But I would like
this function to work *preferable* under both linux, mac and windows
pc's....

My guess is that the code should be changed to something like:

int(double testval)
{
Const EXP_BITS = %01111111111100000000000000000000

return (testval && EXP_BITS); /* returns either 0 or 1 ? */
}

But I guess EXP_BITS is completely wrong defined, so how to make it work
- and are there better existing ways to check for Inf or NaN???

It would be nice with 2 functions: One that tests for plus/minus Inf and
one that checks for NaN, if there's any difference? I didn't really
understood the bit-pattern-difference between NaN and Inf...


Best regards / Med venlig hilsen
Martin Jørgensen
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Martin Jørgensen wrote:
-snip-
It would be nice with 2 functions: One that tests for plus/minus Inf and
one that checks for NaN, if there's any difference? I didn't really
understood the bit-pattern-difference between NaN and Inf...

Basically I have a variable that contains -1.#IND00000000000...
according to MS visual studio 2005... I thought that this was (-inf) so
I made a check:

....
if( val < 0)
do something <- never got here....

I hope somebody can figure this out?


Best regards / Med venlig hilsen
Martin Jørgensen
 
J

Joe Smith

Martin Jørgensen said:
Hi,

I found the code below from
http://www.blitzbasic.com/Community/posts.php?topic=55633

------
' Check if number is finite.


Local u:Double = 2 ' also works for floats

For Local n = 1 To 12
Print isfinite(u) + " " + u
u :* u
Next

Print
Print "What about NaN?"
Print

u = u - u
Print isfinite(u) + " " + u


Function isfinite( x:Double ) ' assumes Intel byte order

Const EXP_BITS = %01111111111100000000000000000000

Local bits = ( Int Ptr Varptr x )[1] ' [0] for Mac?

Return ( bits & EXP_BITS ) <> EXP_BITS ' exponent is all 1s for infinity
or NaN

End Function


------

I need something like that - but the author writes that "This is intel
only. Anybody want to make it multiplatform? It shouldn't be difficult,
but I don't have a Mac".

The code above doesn't look like "standard C" to me... But I would like
this function to work *preferable* under both linux, mac and windows
pc's....

My guess is that the code should be changed to something like:

int(double testval)
{
Const EXP_BITS = %01111111111100000000000000000000

return (testval && EXP_BITS); /* returns either 0 or 1 ? */
}

But I guess EXP_BITS is completely wrong defined, so how to make it work -
and are there better existing ways to check for Inf or NaN???

It would be nice with 2 functions: One that tests for plus/minus Inf and
one that checks for NaN, if there's any difference? I didn't really
understood the bit-pattern-difference between NaN and Inf...

The source snippet might look different to you than me, but it seems to be
missing about ten tokens in order to be C. joe
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Martin Jørgensen wrote:
-snip-
understood the bit-pattern-difference between NaN and Inf...

Addition: You can generate -1.#IND000000... by:

#include math.h

....
var = sqrt (-10);
....

var = -1.#IND000000.., according to MS visual studio 2005 (just in case
somebody wants to try it out).


Best regards / Med venlig hilsen
Martin Jørgensen
 
B

bert

Martin said:
Martin Jørgensen wrote:
-snip-


Basically I have a variable that contains -1.#IND00000000000...
according to MS visual studio 2005... I thought that this was (-inf) so
I made a check:

...
if( val < 0)
do something <- never got here....

I hope somebody can figure this out?
Martin Jørgensen

The IEEE floating point standard says that any comparison
in which one operand is a NaN should evaluate to FALSE.
So the following counter-intuitive test meets your needs:

if (val == val)
do_nothing ( );
else
report_NaN (val);

unless an over-eager (and incorrect) compiler optimises
half of it away . . .
--
 
P

pete

Martin Jørgensen wrote:
Basically I have a variable that contains -1.#IND00000000000...
according to MS visual studio 2005...
I thought that this was (-inf) so
I made a check:

...
if( val < 0)
do something <- never got here....

I hope somebody can figure this out?

exp(DBL_MAX) is a range error.
sqrt(-1) is a domain error.

/* BEGIN new.c */

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

int main(void)
{
double x = -exp(DBL_MAX);
double y = sqrt(-1);

printf("-exp(DBL_MAX) is %f\n", x);
printf("sqrt(-1) is %f\n", y);
return 0;
}

/* END new.c */


N869
7.12.1 Treatment of error conditions
[#1] The behavior of each of the functions in <math.h> is
specified for all representable values of its input
arguments, except where stated otherwise.
[#2] For all functions, a domain error occurs if an input
argument is outside the domain over which the mathematical
function is defined. The description of each function lists
any required domain errors; an implementation may define
additional domain errors, provided that such errors are
consistent with the mathematical definition of the
function.182) On a domain error, the function returns an
implementation-defined value; whether the integer expression
errno acquires the value EDOM is implementation-defined.
[#3] Similarly, a range error occurs if the mathematical
result of the function cannot be represented in an object of
the specified type, due to extreme magnitude. A floating
result overflows if the magnitude of the mathematical result
is finite but so large that the mathematical result cannot
be represented, without extraordinary roundoff error, in an
object of the specified type. If a floating result
overflows and default rounding is in effect, or if the
mathematical result is an exact infinity (for example
log(0.0)), then the function returns the value of the macro
HUGE_VAL, HUGE_VALF, or HUGE_VALL according to the return
type, with the same sign as the correct value of the
function; whether errno acquires the value ERANGE when a
range error occurs is implementation-defined. The result
underflows if the magnitude of the mathematical result is so
small that the mathematical result cannot be
represented, without extraordinary roundoff error, in an
object of the
specified type. If the result underflows, the function
returns a value whose magnitude is no greater than the
smallest normalized positive number in the specified type
and is otherwise implementation-defined; whether errno
acquires the value ERANGE is implementation-defined.
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

pete said:
Martin Jørgensen wrote:




exp(DBL_MAX) is a range error.
sqrt(-1) is a domain error.
-snip-

Yes, thanks but you're only printing out the values using printf(). You
didn't make the if-test...


Best regards / Med venlig hilsen
Martin Jørgensen
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

bert said:
The IEEE floating point standard says that any comparison
in which one operand is a NaN should evaluate to FALSE.
So the following counter-intuitive test meets your needs:

if (val == val)
do_nothing ( );
else
report_NaN (val);

Ok, thanks a lot - it works here and it was a lot easier than I
feared... And how do I check for plus/minus inf ?


Best regards / Med venlig hilsen
Martin Jørgensen
 
J

jacob navia

Martin Jørgensen a écrit :
Hi,

I found the code below from
http://www.blitzbasic.com/Community/posts.php?topic=55633

------
' Check if number is finite.


Local u:Double = 2 ' also works for floats

For Local n = 1 To 12
Print isfinite(u) + " " + u
u :* u
Next

Print
Print "What about NaN?"
Print

u = u - u
Print isfinite(u) + " " + u


Function isfinite( x:Double ) ' assumes Intel byte order

Const EXP_BITS = %01111111111100000000000000000000

Local bits = ( Int Ptr Varptr x )[1] ' [0] for Mac?

Return ( bits & EXP_BITS ) <> EXP_BITS ' exponent is all 1s for
infinity or NaN

End Function


------

I need something like that - but the author writes that "This is intel
only. Anybody want to make it multiplatform? It shouldn't be difficult,
but I don't have a Mac".

The code above doesn't look like "standard C" to me... But I would like
this function to work *preferable* under both linux, mac and windows
pc's....

My guess is that the code should be changed to something like:

int(double testval)
{
Const EXP_BITS = %01111111111100000000000000000000

return (testval && EXP_BITS); /* returns either 0 or 1 ? */
}

But I guess EXP_BITS is completely wrong defined, so how to make it work
- and are there better existing ways to check for Inf or NaN???

It would be nice with 2 functions: One that tests for plus/minus Inf and
one that checks for NaN, if there's any difference? I didn't really
understood the bit-pattern-difference between NaN and Inf...


Best regards / Med venlig hilsen
Martin Jørgensen

Standard C has several functions for this:
1) isfinite: returns true if its argument is finite
2) isinf: returns true if its argument is infinite
3) isnormal: returns true if its argument is normal
4) fpclassify returns the type of its argument.

See the documentation of your compiler system.

P.S. This will work in standard C, not in Visual Studio.
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

jacob navia wrote:
-snip-
Standard C has several functions for this:
1) isfinite: returns true if its argument is finite
2) isinf: returns true if its argument is infinite
3) isnormal: returns true if its argument is normal
4) fpclassify returns the type of its argument.

See the documentation of your compiler system.
Ok.

P.S. This will work in standard C, not in Visual Studio.

Is visual studio 2005 not standard C? I think I disabled something
that's on by default so I think it understands standard C at least... At
least I've had no problems yet with standard C on it (or is it ANSI C?
Don't know if there's any difference)....


Best regards / Med venlig hilsen
Martin Jørgensen
 
R

Richard Heathfield

Martin Jørgensen said:
jacob navia wrote:
-snip-


Is visual studio 2005 not standard C?

Yes and no. VStudio conforms to ISO/IEC 9899:1990 (when you "disable
Microsoft extensions" in the project settings), modulo some trivial and
much-unused dark corners of the language. (Never come across these myself
AFAICR, but people here in clc have occasionally waxed lyrical on the
subject.)

But it doesn't conform to ISO/IEC 9899:1999, which is what you'd need if you
wanted to use Jacob Navia's suggestions. Having said that, almost no C
compilers conform to that later spec - and so, even if VStudio did give you
access to them, your code would still not be portable.
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Richard said:
Martin Jørgensen said: -snip-



Yes and no. VStudio conforms to ISO/IEC 9899:1990 (when you "disable
Microsoft extensions" in the project settings), modulo some trivial and

Exactly! That is what I did (disabled those stupid extensions).
much-unused dark corners of the language. (Never come across these myself
AFAICR, but people here in clc have occasionally waxed lyrical on the
subject.)

But it doesn't conform to ISO/IEC 9899:1999, which is what you'd need if you
wanted to use Jacob Navia's suggestions. Having said that, almost no C
compilers conform to that later spec - and so, even if VStudio did give you
access to them, your code would still not be portable.

isinf and isfinite looks to me like they also exists under unix, so
doesn't that mean it would probably be portable?


Best regards / Med venlig hilsen
Martin Jørgensen
 
R

Richard Heathfield

Martin Jørgensen said:
isinf and isfinite looks to me like they also exists under unix, so
doesn't that mean it would probably be portable?

That depends entirely on your definition of "portable". :)
 
J

jacob navia

Martin Jørgensen a écrit :
Exactly! That is what I did (disabled those stupid extensions).



isinf and isfinite looks to me like they also exists under unix, so
doesn't that mean it would probably be portable?


Best regards / Med venlig hilsen
Martin Jørgensen

Visual studio conforms to the obsolete C standard of 1989.
It has:
isnan(double)
isnanf(float)
finitef(float)
finite(double)

Those functions can solve your problem too.
 
K

Keith Thompson

jacob navia said:
Visual studio conforms to the obsolete C standard of 1989.
It has:
isnan(double)
isnanf(float)
finitef(float)
finite(double)

Those functions can solve your problem too.

To be clear, the C89/C90 standard doesn't define those functions.
(I won't comment on whether the C89/C90 standard is "obsolete".)
 
R

Richard Heathfield

jacob navia said:
Visual studio conforms to the obsolete C standard of 1989.

The 1989 Standard is far from obsolete. It is still the current de facto
Standard, and will remain so until C99 is widely implemented. That day
appears to be some way off - the GNU people have shied away from full
conformance to C99, and Microsoft have ignored it completely.

The C Standard is of no value unless it enables us to write portable code.
C99 features are, quite simply, not even remotely as portable as C89
features.
 
J

jacob navia

Richard Heathfield a écrit :
jacob navia said:




The 1989 Standard is far from obsolete. It is still the current de facto
Standard, and will remain so until C99 is widely implemented. That day
appears to be some way off - the GNU people have shied away from full
conformance to C99,

The issues with gcc are VERY minor. It is a good C99 implementation, and
can be used without any problems.

and Microsoft have ignored it completely.

Yes
The C Standard is of no value unless it enables us to write portable code.

This is your opinion. Your are entitled to it Mr Heathfield, but it is
not mine anyway. There are people that will stay in the past, longing
for the lost "golden times"...

"Portability" for you means "taking the worst features of each
implementation".

There are C99 compilers under windows, and under Unix.
 
J

jacob navia

Richard Heathfield a écrit :
jacob navia said:




ROTFL! Well, that's all right then!

Those are the operating systems mentioned in the original poster's
message.

You speak about "portability", as it was necessary for every piece of
code to be potentially portable to all possible machines. This is mostly
never the case. Many people do not care at all if their code can run
without modifications at some embedded system with a 15 year old
compiler you see?

Some code running with visual studio or under a Mac OSx or similar
will make so many hidden assumptions about RAM size, disk space, etc etc
that it will NEVER run in the "System X" running in the toaster
with 16k of ram.

So What?
 
R

Richard Heathfield

jacob navia said:
Richard Heathfield a écrit :

Those are the operating systems mentioned in the original poster's
message.

He also mentioned the Mac.
You speak about "portability", as it was necessary for every piece of
code to be potentially portable to all possible machines.

The general assumption in comp.lang.c is that the code is targeted at a
hosted implementation of unknown provenance (unless it is specifically
mentioned that a freestanding implementation is targeted). If the platform
matters, well, there are other newsgroups where such discussions can be
held.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top