invalid floating point value

A

Allin Cottrell

OK, I realize that what I am asking here is not likely to have a
answer within the C standard. Nonetheless, it is not specific
to any particular platform, so I'll hazard the question anyway.

A C double can be aliased by an array of unsigned char, to which
any desired byte pattern may be written. Is there any somewhat
portable way of assigning a byte pattern such that the result
will, with very high probability, _not_ count as a valid double?

I ask because I'm in search of a mechanism for flagging "missing
values" in an array of doubles. I'm aware that the "best" (fully
portable) way probably involves setting up an ancillary array, or
making the basic data-type not a straight double but a struct of
some sort. But in context this would be a royal pain. One
common solution is to flag "missing" with a specific value such
as -999.0. I'm wondering if that can be improved upon without
resorting to a wider data type.

Allin Cottrell
Wake Forest University
 
G

Gordon Burditt

OK, I realize that what I am asking here is not likely to have a
answer within the C standard. Nonetheless, it is not specific
to any particular platform, so I'll hazard the question anyway.

A C double can be aliased by an array of unsigned char, to which
any desired byte pattern may be written. Is there any somewhat
portable way of assigning a byte pattern such that the result
will, with very high probability, _not_ count as a valid double?

NO.

However, many implementations use IEEE floating point, which has a
oddball value (or set of values) called a NaN (Not A Number). If
it is available on your implementation, this is a reasonable candidate
for an invalid value. Further, arithmetic with a NaN almost always
results in a NaN.

double x;
... put a value in x ...;
if (x != x ) { ... you have a NaN here ... ; }
(some compilers might get this wrong, though.)

Some ways to get hold of a NaN include 0.0/0.0 and log(0.0). Note
that the "most portable" way does NOT involve overlaying a double
with bytes and stuffing something into the bytes.

Other possibilities include using a very large positive or negative
value, which cannot possibly be a valid value. For example, 1.0e30
is likely not a valid value for an electric bill balance, but it
might get you in the news if you mistakenly send one out for that
amount anyway. 1.0e30 is also within the ANSI C minimum range for
float and double.

Gordon L. Burditt
 
M

Michael Mair

NO.

However, many implementations use IEEE floating point, which has a
oddball value (or set of values) called a NaN (Not A Number). If
it is available on your implementation, this is a reasonable candidate
for an invalid value. Further, arithmetic with a NaN almost always
results in a NaN.

Yep. Import is the *almost*; can give you some cheesy errors.

Nice story on the side: A colleague of mine once had the problem that
a "matrix" he was working with suddenly seemed only able to hold 0.0
as values. After searching for some time he came to me and we went
through with the debugger, finding that at one particular point the
"matrix" (still filled with zeros) scaled with 1/inf and all the zeros
got into a sort of NaN state but did not print as NaNs as all other NaNs
would have...
Not the same problem, I know, but I think it is good to know that
these things still can happen with IEEE FPs...

double x;
... put a value in x ...;
if (x != x ) { ... you have a NaN here ... ; }
(some compilers might get this wrong, though.)

Some ways to get hold of a NaN include 0.0/0.0 and log(0.0). Note
that the "most portable" way does NOT involve overlaying a double
with bytes and stuffing something into the bytes.

Or you can use the isnan() macro from <math.h>
(I am not sure at the moment whether this is only there in C99 or not)

Other possibilities include using a very large positive or negative
value, which cannot possibly be a valid value. For example, 1.0e30
is likely not a valid value for an electric bill balance, but it
might get you in the news if you mistakenly send one out for that
amount anyway. 1.0e30 is also within the ANSI C minimum range for
float and double.

On another note: If you only want to flag that there is some
invalid value out there, you can use an errno-like mechanism and
check in a test mode after every assignment, perhaps even aborting
the program after throwing out the necessary info using assert(0).
Easier to do in a portable way.

If you really want to use you actual double values and are fairly
sure that you will only use IEEE doubles, produce a NaN and then
write to the lower 32 Bit of the mantissa whatever you think
befitting to signal the specific condition, e.g. 0xdeadbeef.
However, this information might not get to you as expected if there
are intermediate steps where the value gets loaded into some register
and written back.


Cheers
Michael
 
P

pete

Allin said:
OK, I realize that what I am asking here is not likely to have a
answer within the C standard. Nonetheless, it is not specific
to any particular platform, so I'll hazard the question anyway.

A C double can be aliased by an array of unsigned char, to which
any desired byte pattern may be written. Is there any somewhat
portable way of assigning a byte pattern such that the result
will, with very high probability, _not_ count as a valid double?

I ask because I'm in search of a mechanism for flagging "missing
values" in an array of doubles. I'm aware that the "best" (fully
portable) way probably involves setting up an ancillary array, or
making the basic data-type not a straight double but a struct of
some sort. But in context this would be a royal pain. One
common solution is to flag "missing" with a specific value such
as -999.0. I'm wondering if that can be improved upon without
resorting to a wider data type.

Instead of -999.0, use either HUGE_VAL or -HUGE_VAL, from math.h.
 
D

Dan Pop

In said:
A C double can be aliased by an array of unsigned char, to which
any desired byte pattern may be written. Is there any somewhat
portable way of assigning a byte pattern such that the result
will, with very high probability, _not_ count as a valid double?

Before IEEE 754, typical floating point representations had no invalid
bit patterns. A single rule was used for interpreting any bit pattern
(with the possible exception of all bits 0, which could be interpreted
as an exact representation of 0.0, regardless of the rule).
I ask because I'm in search of a mechanism for flagging "missing
values" in an array of doubles. I'm aware that the "best" (fully
portable) way probably involves setting up an ancillary array, or
making the basic data-type not a straight double but a struct of
some sort. But in context this would be a royal pain. One
common solution is to flag "missing" with a specific value such
as -999.0. I'm wondering if that can be improved upon without
resorting to a wider data type.

If you can afford in-band signalling, by all means, use it. DBL_MIN and
DBL_MAX are the most likely a priori candidates.

OTOH, if you can afford assuming IEEE 754 floating point (the PDP-11 is
dead, the VAX is dead, IBM mainframes might still be posing a problem)
you can choose Inf or NaN for this purpose. C99 has methods for testing
for them (isinf, isnan), but I don't know how portable they are to C89
implementations. Ditto for isfinite, which checks that a floating point
value is neither infinite nor a NaN.

Dan
 
D

Dik T. Winter

> Before IEEE 754, typical floating point representations had no invalid
> bit patterns. A single rule was used for interpreting any bit pattern
> (with the possible exception of all bits 0, which could be interpreted
> as an exact representation of 0.0, regardless of the rule).

What were typical floating point representations? I know that the
CDC Cyber, Cray 1, Vax and Gould all had a floating point bit pattern
that would never be generated by a valid operation, except perhaps on
overflow or things like that.
 
D

Dan Pop

In said:
What were typical floating point representations? I know that the
CDC Cyber, Cray 1, Vax and Gould all had a floating point bit pattern
that would never be generated by a valid operation, except perhaps on
overflow or things like that.

I'm not aware of any bit pattern that wouldn't represent a valid value for
the IBM 360, PDP-11 and the VAX. Ditto for certain representations used
on systems with no floating point hardware support.

Dan
 
K

Keith Thompson

OTOH, if you can afford assuming IEEE 754 floating point (the PDP-11 is
dead, the VAX is dead, IBM mainframes might still be posing a problem)
you can choose Inf or NaN for this purpose. C99 has methods for testing
for them (isinf, isnan), but I don't know how portable they are to C89
implementations. Ditto for isfinite, which checks that a floating point
value is neither infinite nor a NaN.

The VAX isn't entirely dead; I have an account on one running OpenVMS
6.2. At my previous job, we had a mix of VAX and Alpha boxes running
production code under OpenVMS, but they may have switched over to just
Alphas since then. (The Alpha, which is also approaching the end of
its lifetime, supports both VAX and IEEE floating-point formats.)

Cray has its own non-IEEE floating-point format as well, but most
(all?) of their newer systems use IEEE.

My knowledge is incomplete, but I suspect that IBM mainframes are the
last major holdout of non-IEEE floating-point.
 
D

Dik T. Winter

>
> I'm not aware of any bit pattern that wouldn't represent a valid value for
> the IBM 360, PDP-11 and the VAX. Ditto for certain representations used
> on systems with no floating point hardware support.

Note that I wrote "not generated", not "invalid". In IEEE there are also
no invalid bitpatterns. But whatever, from the PDP11/04/34/45/55/60
processor hndbook, 1978-1979, DEC 1978, page 250 (also valid for the VAX):
"The Undefined Variable
The undefined variable is any bit pattern with a sign bit of one and a
biased exponent of zero. The term undefined variable is used to
indicate that these bit patterns are not assigned a corresponding
floating point arithmetic value. An undefined variable is frequently
referred to as '-0' elsewhere in this chapter."
I do not have an IBM POP, but I think it will also generate only one
form of zero as the result of an operation, so that machine has also
many bit patterns that are not generated and can be used to indicate
an undefined variable. And I think that most software implementations
also represent 0.0 in a single way out of the many choices. Actually
I do only know two machines that have *no* pattern that cannot be
generated. One is the Electrologica X8 that prefers to generate -0.0,
but on occasion generates +0.0, and an old ICL machine that had no
representation for 0.0 (also a joy of course).
 
A

Allin Cottrell

pete said:
Allin Cottrell wrote:


Instead of -999.0, use either HUGE_VAL or -HUGE_VAL, from math.h.

Thank to all for the suggestions. It seems that the above, or
DBL_MAX/DBL_MIN are probably the best bets for my situation.

Allin Cottrell
 
D

Dan Pop

In said:
(e-mail address removed) (Dan Pop) writes:
[...]
OTOH, if you can afford assuming IEEE 754 floating point (the PDP-11 is
dead, the VAX is dead, IBM mainframes might still be posing a problem)
you can choose Inf or NaN for this purpose. C99 has methods for testing
for them (isinf, isnan), but I don't know how portable they are to C89
implementations. Ditto for isfinite, which checks that a floating point
value is neither infinite nor a NaN.

The VAX isn't entirely dead; I have an account on one running OpenVMS
6.2.

By this argument, the PDP-11 (or even the PDP-8) isn't entirely dead,
either.

The point is that VAX hardware hasn't been manufactured for almost a
decade, so any serious shop using VAXen has already migrated to something
else, even if the VAXen are still kept running until they break, for
one reason or another.

Dan
 
D

Dan Pop

In said:
Note that I wrote "not generated", not "invalid".

I couldn't care less: you wrote "not generated" in reply to a post of mine
that didn't contain these words.
In IEEE there are also no invalid bitpatterns.

"Invalid" should be read in the context of the thread, i.e. not
representing any floating point value.
But whatever, from the PDP11/04/34/45/55/60
processor hndbook, 1978-1979, DEC 1978, page 250 (also valid for the VAX):
"The Undefined Variable
The undefined variable is any bit pattern with a sign bit of one and a
biased exponent of zero. The term undefined variable is used to
indicate that these bit patterns are not assigned a corresponding
floating point arithmetic value. An undefined variable is frequently
referred to as '-0' elsewhere in this chapter."

Why do they refer to it as -0 if it's not assigned a value?
I do not have an IBM POP, but I think it will also generate only one
form of zero as the result of an operation, so that machine has also
many bit patterns that are not generated and can be used to indicate
an undefined variable. And I think that most software implementations
also represent 0.0 in a single way out of the many choices. Actually
I do only know two machines that have *no* pattern that cannot be
generated. One is the Electrologica X8 that prefers to generate -0.0,
but on occasion generates +0.0, and an old ICL machine that had no
representation for 0.0 (also a joy of course).

The OP was looking for a bit pattern that could be reliably used
*everywhere* as not corresponding to any floating point value.

Dan
 
D

Dik T. Winter

>
> Why do they refer to it as -0 if it's not assigned a value?

Ask them. Anyhow, using such a value in an operation results in a trap.
> The OP was looking for a bit pattern that could be reliably used
> *everywhere* as not corresponding to any floating point value.

Not entirely true. He was asking for a value that could be used to
distinguish non-initialized valiables from initialized vairables
(note the mention of -999.0 commonly being used). A value that is
never generated by the processor could serve very well for such a
purpose.
 
D

Dan Pop

In said:
Not entirely true. He was asking for a value that could be used to
distinguish non-initialized valiables from initialized vairables
(note the mention of -999.0 commonly being used). A value that is
never generated by the processor could serve very well for such a
purpose.

How do you store such a "value" in a variable in the first place?

Dan
 
K

Keith Thompson

How do you store such a "value" in a variable in the first place?

By constructing it as an array of unsigned char, for example. The
phrase "never generated by the processor" is a mildly sloppy, but IMHO
sufficiently clear, way of saying "never generated by the processor
using any floating-point operation".
 
D

Dik T. Winter

>
> How do you store such a "value" in a variable in the first place?

You are dense. Obviously I meant "never generated by the floating-point
part of the processor".
 
D

Dan Pop

In said:
By constructing it as an array of unsigned char, for example.

Are you sure you've been following the discussion? Pay special attention
to the underlined bits.

So, you seem to be agreeing with me, that a bit pattern is what the OP
was after.

Dan
 
D

Dan Pop

In said:
You are dense.
Nope.

Obviously I meant "never generated by the floating-point part of the
processor".

And this is how I interpreted it. But you called it a "value" and
objected to my treating it as a bit pattern. So, please make up your
mind.

Dan
 
D

Dik T. Winter

>
> Nope.
>
>
> And this is how I interpreted it. But you called it a "value" and
> objected to my treating it as a bit pattern. So, please make up your
> mind.

I use "value" and "bit pattern" here interchangably. It was *not*
your use of "bit pattern" I objected to. It was your use of
"not corresponding to any floating point value" I objected to.
 
D

Dan Pop

In said:
I use "value" and "bit pattern" here interchangably. It was *not*
your use of "bit pattern" I objected to. It was your use of
"not corresponding to any floating point value" I objected to.

My usage was consistent to the OP's:

A C double can be aliased by an array of unsigned char, to which
any desired byte pattern may be written. Is there any somewhat
portable way of assigning a byte pattern such that the result
will, with very high probability, _not_ count as a valid double?

And, unless I'm missing something, you've been unable to produce such a
bit pattern, so your contributions to this thread have consisted of pure
noise...

Dan
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top