Discussion:
Testing for very small doubles with DBL_EPSILON and _isnan()
(too old to reply)
Olumide
2009-06-05 00:21:30 UTC
Permalink
Hello,

I recently had a colleague introduce me to the variable macro
DBL_EPSILON and the function _isnan(), because some of my functions
return 1.#QNANO values. However, I'm not sure of of how best to use
DBL_EPSILON and _isnan(). Which is the better way to test for a small
double:

Method 1: _isnan( really_small_double );

Method 2: if( really_small_double < DBL_EPSILON ) // do stuff

Thanks,

- Olumide
Keith Thompson
2009-06-05 02:30:04 UTC
Permalink
Post by Olumide
I recently had a colleague introduce me to the variable macro
DBL_EPSILON and the function _isnan(), because some of my functions
return 1.#QNANO values. However, I'm not sure of of how best to use
DBL_EPSILON and _isnan(). Which is the better way to test for a small
Method 1: _isnan( really_small_double );
Method 2: if( really_small_double < DBL_EPSILON ) // do stuff
Neither.

C99 has a standard macro isnan(); if your implementation doesn't
support it, it might instead have something similar called "_isnan()".
You'll have to consult your implementation's documentation to find out
exactly what it does. But it almost certainly tests whether its
argument is a NaN -- which stands for "Not a Number". It's not a
really small number; it's not a number at all.

DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0. Whether that qualifies as "really small" is
something you'll have to decide for yourself. It depends on the
requirements of your application. There is no single answer.

Oh, and (x < DBL_EPSILON) is true for very large negative numbers.

I *think* this applies to both C and C++ (I'm reading and posting in
comp.lang.c), but cross-posts between comp.lang.c and comp.lang.c++
are almost never a good idea.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
JosephKK
2009-06-06 21:51:24 UTC
Permalink
Post by Keith Thompson
Post by Olumide
I recently had a colleague introduce me to the variable macro
DBL_EPSILON and the function _isnan(), because some of my functions
return 1.#QNANO values. However, I'm not sure of of how best to use
DBL_EPSILON and _isnan(). Which is the better way to test for a small
Method 1: _isnan( really_small_double );
Method 2: if( really_small_double < DBL_EPSILON ) // do stuff
Neither.
C99 has a standard macro isnan(); if your implementation doesn't
support it, it might instead have something similar called "_isnan()".
You'll have to consult your implementation's documentation to find out
exactly what it does. But it almost certainly tests whether its
argument is a NaN -- which stands for "Not a Number". It's not a
really small number; it's not a number at all.
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution. The difference can be pretty subtle,
but consider: if you are dealing with largish quantities, say
Avogadro's number, and you want to know the number of atoms delta
resolution that can be represented it would still be many trillions.
But the accuracy ratio scales directly with the size of the numbers
represented, and this is but one of the contributing components to a
property called numerical instability.
Post by Keith Thompson
Whether that qualifies as "really small" is
something you'll have to decide for yourself. It depends on the
requirements of your application. There is no single answer.
Oh, and (x < DBL_EPSILON) is true for very large negative numbers.
I *think* this applies to both C and C++ (I'm reading and posting in
comp.lang.c), but cross-posts between comp.lang.c and comp.lang.c++
are almost never a good idea.
Martin Eisenberg
2009-06-06 22:28:59 UTC
Permalink
On Thu, 04 Jun 2009 19:30:04 -0700, Keith Thompson
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next
representable number above 1.0.
Not really. It specifies the guaranteed accuracy of
mathematical operations, not the resolution.
Yes it does. C++98 final draft, 18.2.1.2/20 says:

| static T epsilon() throw();
|
| Machine epsilon: the difference between 1 and the least value
| greater than 1 that is representable. 8)
|
| 8) Equivalent to FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON.

The C++ standard does not define accuracy, but IEEE754 mandates that
the relative error of basic operations not exceed 1 ulp which roughly
means the interval [-2*epsilon, epsilon].


Martin
--
Quidquid latine scriptum est, altum videtur.
Martin Eisenberg
2009-06-06 22:42:28 UTC
Permalink
Post by Martin Eisenberg
The C++ standard does not define accuracy, but IEEE754 mandates
that the relative error of basic operations not exceed 1 ulp
which roughly means the interval [-2*epsilon, epsilon].
Correction: [-1,1]*epsilon.


Martin
--
Quidquid latine scriptum est, altum videtur.
JosephKK
2009-06-08 05:31:22 UTC
Permalink
On Sat, 6 Jun 2009 22:28:59 +0000 (UTC), Martin Eisenberg
Post by Martin Eisenberg
On Thu, 04 Jun 2009 19:30:04 -0700, Keith Thompson
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next
representable number above 1.0.
Not really. It specifies the guaranteed accuracy of
mathematical operations, not the resolution.
| static T epsilon() throw();
|
| Machine epsilon: the difference between 1 and the least value
| greater than 1 that is representable. 8)
|
| 8) Equivalent to FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON.
The C++ standard does not define accuracy, but IEEE754 mandates that
the relative error of basic operations not exceed 1 ulp which roughly
means the interval [-2*epsilon, epsilon].
Martin
I was talking in clc, was not mindful of crossposting. Besides being
more of a hardware type i care more about IEEE-754 terminology.
j
James Kuyper
2009-06-06 23:32:32 UTC
Permalink
...
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really. ...
Yes, really. The C standard defines it as: "the difference between 1 and
the least value greater than 1 that is representable in the given
floating point type ..." (5.2.4.2.2p11). Since this is cross-posted to
C++, I'll also mention that the C++ standard incorporates the C standard
library by reference (1.2p2) and specifically mentions both <float.h>
(D.5p1) and DBL_EPSILON (C.2p4) as features of that library which are so
incorporated, and specifies that for <cfloat> ”The contents are the
same as the Standard C library header <float.h>”. (18.2.2p4).
... It specifies the guaranteed accuracy of mathematical
operations, not the resolution The difference can be pretty subtle,
but consider: if you are dealing with largish quantities, say
Avogadro's number, and you want to know the number of atoms delta
resolution that can be represented it would still be many trillions.
But the accuracy ratio scales directly with the size of the numbers
represented, and this is but one of the contributing components to a
property called numerical instability.
The definition of DBL_EPSILON is cited above. It's quite simple, and
makes no mention of any of those issues. Those issues are certainly
related to it, but not in any way that justifies saying "Not really.".
James Kuyper
2009-06-06 23:50:58 UTC
Permalink
incorporated, and specifies that for <cfloat> ”The contents are the
same as the Standard C library header <float.h>”. (18.2.2p4).
Sorry about that - but I've finally figured out what's going wrong. My
computer has software installed that lets me easily insert characters in
encodings and fonts designed for showing both Chinese and English text.d
It switches modes automatically when I hit Shift-Space, or Ctrl-Space,
key combinations that I've been hitting by accident far too frequently
lately.
incorporated, and specifies that for <cfloat.h> "The contents are the
same as the Standard C library header <float.h>" (18.2.2p4).
JosephKK
2009-06-08 05:38:28 UTC
Permalink
On Sat, 06 Jun 2009 23:50:58 GMT, James Kuyper
Post by James Kuyper
incorporated, and specifies that for <cfloat> �The contents are the
same as the Standard C library header <float.h>�. (18.2.2p4).
Sorry about that - but I've finally figured out what's going wrong. My
computer has software installed that lets me easily insert characters in
encodings and fonts designed for showing both Chinese and English text.d
It switches modes automatically when I hit Shift-Space, or Ctrl-Space,
key combinations that I've been hitting by accident far too frequently
lately.
incorporated, and specifies that for <cfloat.h> "The contents are the
same as the Standard C library header <float.h>" (18.2.2p4).
Well shit. The standards say what the standards say. I am corrected
on what they say. It does not alter the real properties of the real
hardware, nor the mathematical properties thereof. Overextend your
trust in the programming language standards at your own risk.
James Kuyper
2009-06-08 11:00:51 UTC
Permalink
JosephKK wrote:
...
Post by JosephKK
Well shit. The standards say what the standards say. I am corrected
on what they say. It does not alter the real properties of the real
hardware, nor the mathematical properties thereof. ...
DBL_EPSILON Is not a mathematical abstraction, it is a macro defined in
the C standard library, with a value whose meaning is specified by the C
standard.

When you wrote "Not really.", you were objecting to a true statement
about DBL_EPSILON, not a statement about "the real properties of real
hardware".

When you wrote the sentence which starts "It specifies ...", the subject
of that sentence was "It", which in context had to be a reference to the
use of DBL_EPSILON in the message you were responding to. Again, what
you said about "it" may have been true with regard to some entity
related to "the real properties of real hardware", but you didn't
identify which entity that is; it certainly is not DBL_EPSILON.
Post by JosephKK
... Overextend your
trust in the programming language standards at your own risk.
I trust DBL_EPSILON to be the difference between 1.0 and the next number
after 1.0 that is representable as a double. Combining that fact with
the definition of C's floating point model given in 5.2.4.2.2p1-2, and
the value of FLT_RADIX, I can calculate the spacing between x and the
next representable number for any value of x that satisfies (DBL_MIN <=
x && x < DBL_MAX) || (-DBL_MAX <= x && x < -DBL_MIN).

Thinking that DBL_EPSILON means anything other than that would be
"overextending" the definition (as CBFalconer so spectacularly
demonstrated in a recent thread), but that's not because of trusting the
programming language standards too much, but because of misunderstanding
what they say.
JosephKK
2009-06-09 02:10:17 UTC
Permalink
On Mon, 08 Jun 2009 11:00:51 GMT, James Kuyper
Post by James Kuyper
...
Post by JosephKK
Well shit. The standards say what the standards say. I am corrected
on what they say. It does not alter the real properties of the real
hardware, nor the mathematical properties thereof. ...
DBL_EPSILON Is not a mathematical abstraction, it is a macro defined in
the C standard library, with a value whose meaning is specified by the C
standard.
When you wrote "Not really.", you were objecting to a true statement
about DBL_EPSILON, not a statement about "the real properties of real
hardware".
When you wrote the sentence which starts "It specifies ...", the subject
of that sentence was "It", which in context had to be a reference to the
use of DBL_EPSILON in the message you were responding to. Again, what
you said about "it" may have been true with regard to some entity
related to "the real properties of real hardware", but you didn't
identify which entity that is; it certainly is not DBL_EPSILON.
Post by JosephKK
... Overextend your
trust in the programming language standards at your own risk.
I trust DBL_EPSILON to be the difference between 1.0 and the next number
after 1.0 that is representable as a double. Combining that fact with
the definition of C's floating point model given in 5.2.4.2.2p1-2, and
the value of FLT_RADIX, I can calculate the spacing between x and the
next representable number for any value of x that satisfies (DBL_MIN <=
x && x < DBL_MAX) || (-DBL_MAX <= x && x < -DBL_MIN).
Thinking that DBL_EPSILON means anything other than that would be
"overextending" the definition (as CBFalconer so spectacularly
demonstrated in a recent thread), but that's not because of trusting the
programming language standards too much, but because of misunderstanding
what they say.
The C standard says what it says. It defines a few thing in certain
ways. Those definitions are often somewhat at odds with how the
hardware operates and the way that IEEE-754 specifies that they
operate. Thus when the hardware acts differently than what the C
standard specifies, it is not the hardware that is defective.
;
Never mind we are talking past each other.
James Kuyper
2009-06-09 02:49:49 UTC
Permalink
JosephKK wrote:
...
Post by JosephKK
The C standard says what it says. It defines a few thing in certain
ways. Those definitions are often somewhat at odds with how the
hardware operates and the way that IEEE-754 specifies that they
operate. Thus when the hardware acts differently than what the C
standard specifies, it is not the hardware that is defective.
;
Never mind we are talking past each other.
I'd prefer not to be talking past each other. I'm aware that there are
inconsistencies of the kind you mention in some other parts of the
standard; in particular, I've heard that some of the specifications in
Annex F about how signed zeros and signed infinities are supposed to be
handled don't jibe with the IEEE-754.

But is there anything that the standard says about DBL_EPSILON
specifically which is "somewhat at odds with the hardware operates and
the way that IEEE-754 specifies that they operate"? If so, how? I'm at a
loss to imagine how it could be. As far as I know, all floating point
representations have a unique next-representable value after 1.0, and
that would seem to be the only requirement for the definition of
DBL_EPSILON to be meaningful.
Dik T. Winter
2009-06-09 12:42:56 UTC
Permalink
In article <***@4ax.com> "JosephKK"<***@yahoo.com> writes:
...
Post by JosephKK
The C standard says what it says. It defines a few thing in certain
ways. Those definitions are often somewhat at odds with how the
hardware operates and the way that IEEE-754 specifies that they
operate.
In what way is the hardware operation different from the C standard definition
of DBL_EPSILON? Or do you state that in hardware DBL_EPSILON (that is the
difference between 1.0 and the next higher number) is not equal to the
difference between 1.0 and the next higher number? Why not?
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Joe Wright
2009-06-06 23:38:03 UTC
Permalink
Post by JosephKK
Post by Keith Thompson
Post by Olumide
I recently had a colleague introduce me to the variable macro
DBL_EPSILON and the function _isnan(), because some of my functions
return 1.#QNANO values. However, I'm not sure of of how best to use
DBL_EPSILON and _isnan(). Which is the better way to test for a small
Method 1: _isnan( really_small_double );
Method 2: if( really_small_double < DBL_EPSILON ) // do stuff
Neither.
C99 has a standard macro isnan(); if your implementation doesn't
support it, it might instead have something similar called "_isnan()".
You'll have to consult your implementation's documentation to find out
exactly what it does. But it almost certainly tests whether its
argument is a NaN -- which stands for "Not a Number". It's not a
really small number; it's not a number at all.
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution. The difference can be pretty subtle,
but consider: if you are dealing with largish quantities, say
Avogadro's number, and you want to know the number of atoms delta
resolution that can be represented it would still be many trillions.
But the accuracy ratio scales directly with the size of the numbers
represented, and this is but one of the contributing components to a
property called numerical instability.
Yes really. The definition of EPSILON is in simple English:

the difference between 1 and the least value greater
than 1 that is representable in the given floating
point type, b^1-p.

In the case of float that is 2^-23. Consider:

00110100 00000000 00000000 00000000
Exp = 104 (-22)
11101010
Man = .10000000 00000000 00000000
1.19209290e-07

This is the representation of FLT_EPSILON. Adding 1 to it:

00111111 10000000 00000000 00000001
Exp = 127 (1)
00000001
Man = .10000000 00000000 00000001
1.00000012e+00

Consider the mantissa (significand?). The bit at b23 is the 1 and the
bit at b0 is EPSILON. It shows us graphically the limits of precision
and accuracy of a float. The term (1.0 + FLT_EPSILON) is useful in
determining the granularity of a given floating point value.
--
Joe Wright
"Memory is the second thing to go. I forget what the first is."
Eric Sosman
2009-06-07 02:10:55 UTC
Permalink
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really.
Yes, really. In comp.lang.c at any rate; comp.lang.c++
is beyond my knowledge or speculation. 5.2.4.2.2p10 *defines*
DBL_EPSILON as

"the difference between 1 and the least value greater
than 1 that is representable in [double]"

... and goes on to say that it shall not exceed 1E-9.
--
Eric Sosman
***@ieee-dot-org.invalid
Dik T. Winter
2009-06-08 10:19:57 UTC
Permalink
...
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0. =20
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things like
this.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
JosephKK
2009-06-09 02:15:52 UTC
Permalink
Post by Dik T. Winter
...
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0. =20
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things like
this.
Well fudge. The standard defines it the way that it does. That
definition is in conflict with the way the IEEE-745 compliant hardware
operates. And i am a hardware type.
Keith Thompson
2009-06-09 06:37:46 UTC
Permalink
Post by JosephKK
Post by Dik T. Winter
...
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0. =20
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things like
this.
Well fudge. The standard defines it the way that it does. That
definition is in conflict with the way the IEEE-745 compliant hardware
operates. And i am a hardware type.
How so? The definition of DBL_EPSILON isn't about the way the
hardware operates; it's an unambiguous definition of a number. Just
what conflict do you see?
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Richard Herring
2009-06-09 10:08:19 UTC
Permalink
Post by JosephKK
Post by Dik T. Winter
...
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0. =20
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things like
this.
Well fudge.
"When in hole, stop digging".
Post by JosephKK
The standard defines it the way that it does. That
definition is in conflict with the way the IEEE-745 compliant hardware
operates.
Since the definition is entirely in terms of how the hardware operates
("next representable number above 1.0"), how can that be?
Post by JosephKK
And i am a hardware type.
I see. And I always thought hardware was based on logic.
--
Richard Herring
Dik T. Winter
2009-06-09 12:44:39 UTC
Permalink
...
Post by JosephKK
Post by Dik T. Winter
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things
like this.
Well fudge. The standard defines it the way that it does. That
definition is in conflict with the way the IEEE-745 compliant hardware
operates. And i am a hardware type.
In what way does it conflict with how the hardware operates? I have no
idea about what you do mean here. DBL_EPSILON is defined in a certain,
precise, way. I do not see how the hardware comes into it.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
JosephKK
2009-06-10 04:36:22 UTC
Permalink
Post by Dik T. Winter
...
Post by JosephKK
Post by Dik T. Winter
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things
like this.
Well fudge. The standard defines it the way that it does. That
definition is in conflict with the way the IEEE-745 compliant hardware
operates. And i am a hardware type.
In what way does it conflict with how the hardware operates? I have no
idea about what you do mean here. DBL_EPSILON is defined in a certain,
precise, way. I do not see how the hardware comes into it.
I did a study of compliance of 8087 versus the Cyrix and Weitek knock
offs about 25 years ago. The standard has not changed much since. If
you really, really want to know get a copy and study it.

Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
user923005
2009-06-10 06:39:18 UTC
Permalink
Post by JosephKK
...
Post by Dik T. Winter
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really.  It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things
like this.
Well fudge.  The standard defines it the way that it does.  That
definition is in conflict with the way the IEEE-745 compliant hardware
operates.  And i am a hardware type.
In what way does it conflict with how the hardware operates?  I have no
idea about what you do mean here.  DBL_EPSILON is defined in a certain,
precise, way.  I do not see how the hardware comes into it.
I did a study of compliance of 8087 versus the Cyrix and Weitek knock
offs about 25 years ago.  The standard has not changed much since.  If
you really, really want to know get a copy and study it.
Telling Dik Winter to study an applied math paper is like telling
George Marsaglia to read you paper on PRNGs or Donald Knuth to read
your article about the art of computer programming.
Post by JosephKK
Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
I would say that 1E-19 is off by about a factor of ~ 2220 unless you
know something I don't know.
{My calculation would be: eps is 2.0/pow(2.0,53.0) for a 53 bit
mantissa.}
Flash Gordon
2009-06-10 06:38:14 UTC
Permalink
Post by JosephKK
Post by Dik T. Winter
...
Post by JosephKK
Post by Dik T. Winter
Post by JosephKK
Post by Keith Thompson
DBL_EPSILON is the difference between 1.0 and the next representable
number above 1.0.
Not really. It specifies the guaranteed accuracy of mathematical
operations, not the resolution.
It would be better if you read the standard before pronouncing things
like this.
Well fudge. The standard defines it the way that it does. That
definition is in conflict with the way the IEEE-745 compliant hardware
operates. And i am a hardware type.
In what way does it conflict with how the hardware operates? I have no
idea about what you do mean here. DBL_EPSILON is defined in a certain,
precise, way. I do not see how the hardware comes into it.
I did a study of compliance of 8087 versus the Cyrix and Weitek knock
offs about 25 years ago. The standard has not changed much since. If
you really, really want to know get a copy and study it.
Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
So? The C standard says that if the correct value of DBL_EPSILON is
1E-19 then that is what the implementation has to define it as. The
specific value mentioned in the standard is a limit on what it is
allowed to be, not the specific value to be used in every implementation.

To be clear, if the difference between 1.0 and the next representable
number in the floating point format used by the hardware is 1E-19, then
the C standard *requires* that DBL_EPSILON be defined as 1E-19 (this
specific exact value would require base 10 floating point rather than
base 2, which is allowed by the standard).

The C++ standard is, I believe, the same in this respect.
--
Flash Gordon
Dik T. Winter
2009-06-10 10:29:44 UTC
Permalink
...
Post by JosephKK
Post by Dik T. Winter
In what way does it conflict with how the hardware operates? I have no
idea about what you do mean here. DBL_EPSILON is defined in a certain,
precise, way. I do not see how the hardware comes into it.
I did a study of compliance of 8087 versus the Cyrix and Weitek knock
offs about 25 years ago. The standard has not changed much since.
The standard has not changed at all, but the 8087 (and 80187) is not standard
compliant (it was based on a preliminary version of it). As far as I know,
Cyrix and Weitek were standard compliant. Yhe 80287 was the first standard
compliant Intel FP processor.
Post by JosephKK
If
you really, really want to know get a copy and study it.
Do you think I do not know that standard?
Post by JosephKK
Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
Where is written that DBL_EPSILON is something like 1E-9? With IEEE,
DBL_EPSILON equals 2^(-52).
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
JosephKK
2009-06-11 02:07:19 UTC
Permalink
Post by Dik T. Winter
...
Post by JosephKK
Post by Dik T. Winter
In what way does it conflict with how the hardware operates? I have no
idea about what you do mean here. DBL_EPSILON is defined in a certain,
precise, way. I do not see how the hardware comes into it.
I did a study of compliance of 8087 versus the Cyrix and Weitek knock
offs about 25 years ago. The standard has not changed much since.
The standard has not changed at all, but the 8087 (and 80187) is not standard
compliant (it was based on a preliminary version of it).
True that the 8087 was not quite compliant. However the Cyrix
mimicked those errors, but not the Weitek.
Post by Dik T. Winter
As far as I know,
Cyrix and Weitek were standard compliant. Yhe 80287 was the first standard
compliant Intel FP processor.
Somewhere somebody said that storing the X87 80 bit temporary values
required a conversion that was time costly, it was not. Moreover you
could store the 80-bit register contents as well. This as also true
for the 68881 series FPU as well.
Post by Dik T. Winter
Post by JosephKK
If
you really, really want to know get a copy and study it.
Do you think I do not know that standard?
I would not be surprised if you had studied it recently.

I checked its current form dated 2008 and they incorporated decimal
floating point from IEEE-854. Among other things this made many more
software implementations compliant and the hardware of IBM s/390
compliant.
Post by Dik T. Winter
Post by JosephKK
Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
Ah yes, the implementation value may be different from the "C"
standard limit value. Sloppy on my part.
Post by Dik T. Winter
Where is written that DBL_EPSILON is something like 1E-9? With IEEE,
DBL_EPSILON equals 2^(-52).
James Kuyper
2009-06-11 10:15:53 UTC
Permalink
...
Post by JosephKK
Post by JosephKK
Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
Ah yes, the implementation value may be different from the "C"
standard limit value. Sloppy on my part.
Replace "may be different from" with "must be <=", and you more
accurately express the meaning of the standard value.
Dik T. Winter
2009-06-11 12:16:21 UTC
Permalink
...
Post by JosephKK
Post by Dik T. Winter
Post by JosephKK
Post by Dik T. Winter
In what way does it conflict with how the hardware operates? I have
no idea about what you do mean here. DBL_EPSILON is defined in a
certain, precise, way. I do not see how the hardware comes into it.
I did a study of compliance of 8087 versus the Cyrix and Weitek knock
offs about 25 years ago. The standard has not changed much since.
The standard has not changed at all, but the 8087 (and 80187) is not
standard compliant (it was based on a preliminary version of it).
True that the 8087 was not quite compliant.
Yes, Intel wanted the chip design to be complete, although the standard was
not yet finalized. So the 8087 did have only one infinity.
Post by JosephKK
Post by Dik T. Winter
The 80287 was the first
standard compliant Intel FP processor.
Somewhere somebody said that storing the X87 80 bit temporary values
required a conversion that was time costly, it was not. Moreover you
could store the 80-bit register contents as well. This as also true
for the 68881 series FPU as well.
What is the relevance?
Post by JosephKK
Post by Dik T. Winter
Post by JosephKK
If
you really, really want to know get a copy and study it.
Do you think I do not know that standard?
I would not be surprised if you had studied it recently.
Well, I have not. The last time I really studied it was some 20 years ago.
Post by JosephKK
Post by Dik T. Winter
Post by JosephKK
Example: with 53 bits of mantissa, DBL_EPSILON would be closer to
1E-19 rather than 1E-9
Where is written that DBL_EPSILON is something like 1E-9? With IEEE,
DBL_EPSILON equals 2^(-52).
Ah yes, the implementation value may be different from the "C"
standard limit value. Sloppy on my part.
Rather, on most implementations the implementation value *must* be different
from the "C" standard limit value. So in IEEE DBL_EPSILON *must* be 2^(-52).

I do not think there are implementations of C around that get it wrong.
Although I know it is sometimes hard for compiler writers to get such things
right. When Ada compilers started arriving I wrote a program that verified
all floating-point attributes that the language defined. This program was
distributed widely and to my surprise, there was *no* implementation that had
everything correct. Even on our Data General MV4000 the compiler said that
the machine-radix was 2 while it actually was 16.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
pete
2009-06-07 11:03:55 UTC
Permalink
Post by Keith Thompson
Oh, and (x < DBL_EPSILON) is true for very large negative numbers.
Isn't it true for *all* negative numbers?
--
pete
Keith Thompson
2009-06-07 15:11:23 UTC
Permalink
Post by pete
Post by Keith Thompson
Oh, and (x < DBL_EPSILON) is true for very large negative numbers.
Isn't it true for *all* negative numbers?
Of course (and for 0.0), but the intended point of the comparison was
to determine whether x is "really small".
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Olumide
2009-06-05 23:20:14 UTC
Permalink
You misunderstand DBL_EPSILON.  It is not a very small number.  It is
the smallest number that can be added to 1.0 to produce a result >
1.0.  If a double has d digits of precision, then DBL_EPSILON is on
the order of pow(10,-d).  Almost all floating point representations
can handle numbers much smaller.
Thanks everyone. I'm sorry I didn't express myself clearly enough. By
"too small" I mean cannot be represented by a double, thus the value
1.#QNANO (BTW, I'm using Visual Studio .NET 2003). Therefore, I meant
to ask what is the proper technique for testing the result of a
computation is not representable as a double?

Thanks.
Pete Becker
2009-06-05 23:24:56 UTC
Permalink
Post by Olumide
Thanks everyone. I'm sorry I didn't express myself clearly enough. By
"too small" I mean cannot be represented by a double, thus the value
1.#QNANO (BTW, I'm using Visual Studio .NET 2003). Therefore, I meant
to ask what is the proper technique for testing the result of a
computation is not representable as a double?
There's no such thing as too small to represent as a double. Really
really small values become zero. NaNs come from things like 0/0,
inf-inf, etc.

Try this:

double f = 0.0;
while (f != 0)
{
std::cout << f << std::endl;
/* printf("%f\n", f); for the C cross-post */
f /= 2;
}
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)
Pete Becker
2009-06-05 23:34:53 UTC
Permalink
Post by Pete Becker
Post by Olumide
Thanks everyone. I'm sorry I didn't express myself clearly enough. By
"too small" I mean cannot be represented by a double, thus the value
1.#QNANO (BTW, I'm using Visual Studio .NET 2003). Therefore, I meant
to ask what is the proper technique for testing the result of a
computation is not representable as a double?
There's no such thing as too small to represent as a double. Really
really small values become zero. NaNs come from things like 0/0,
inf-inf, etc.
double f = 0.0;
Whoops:

double f = 1.0;
Post by Pete Becker
while (f != 0)
{
std::cout << f << std::endl;
/* printf("%f\n", f); for the C cross-post */
f /= 2;
}
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)
Olumide
2009-06-05 23:54:47 UTC
Permalink
Post by Pete Becker
Post by Olumide
Thanks everyone. I'm sorry I didn't express myself clearly enough. By
"too small" I mean cannot be represented by a double, thus the value
1.#QNANO (BTW, I'm using Visual Studio .NET 2003). Therefore, I meant
to ask what is the proper technique for testing the result of a
computation is not representable as a double?
There's no such thing as too small to represent as a double. Really
really small values become zero. NaNs come from things like 0/0,
inf-inf, etc.
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?

Thanks.
Keith Thompson
2009-06-06 00:50:46 UTC
Permalink
Post by Olumide
Post by Pete Becker
Post by Olumide
Thanks everyone. I'm sorry I didn't express myself clearly enough. By
"too small" I mean cannot be represented by a double, thus the value
1.#QNANO (BTW, I'm using Visual Studio .NET 2003). Therefore, I meant
to ask what is the proper technique for testing the result of a
computation is not representable as a double?
There's no such thing as too small to represent as a double. Really
really small values become zero. NaNs come from things like 0/0,
inf-inf, etc.
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
It's hard to tell.

Is a^b supposed to be a raised to the power b? If so, I'd expect
something like, say, 1e-20 ^ (-100) to yield Infinity, not a NaN.
You'll need to analyze your code, perhaps using a debugger, to
determine where it's going wrong. If you can narrow your code down to
a small self-contained program that exhibits the problem, we can
probably help you -- or, very likely, you'll find the problem yourself
in the process of narrowing it down.

But please decide which language you're using, C or C++, and post just
to the appropriate newsgroup.

Another thing, you see the line "Olumide <***@web.de> writes:" at
the top? That's an attribution line. Please leave those in place for
any quoted text. Thanks.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dik T. Winter
2009-06-06 01:14:11 UTC
Permalink
In article <c9c6b947-5a46-4b86-adb6-***@g20g2000vba.googlegroups.com> Olumide <***@web.de> writes:
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).

So I suspect your a has become negative.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Olumide
2009-06-06 16:13:10 UTC
Permalink
...
 > Perhaps then the problem is a NaN. My functions perform lots of
 > computation of the type: a^b, and occasionally, a is a very small
 > number, while b is negative, so that the result tends to 1/0 . Might
 > this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN.  The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral).  In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
Okay, here is a snip of a typical section of code that occasionally
results in a output being 1.#QNANO:

double deltaX, deltaY, deltaZ;
initializeDeltaXYZ( ... );
double r2 = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
double output = 2 * m_alpha * pow( r2 , m_alpha - 1 ) + 4 * m_alpha *
(m_alpha - 1) * pow( deltaX , 2 ) * pow( r2 , m_alpha - 2 );

What I would like to know is:

1. why output is sometimes evaluated as 1.#QNANO in this case
2. how to test when this happens.

Thanks.
Olumide
2009-06-06 16:15:22 UTC
Permalink
Post by Olumide
Okay, here is a snip of a typical section of code that occasionally
double deltaX, deltaY, deltaZ;
initializeDeltaXYZ( ... );
double r2 = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
double output = 2 * m_alpha * pow( r2 , m_alpha - 1 ) + 4 * m_alpha *
(m_alpha - 1) * pow( deltaX , 2 ) * pow( r2 , m_alpha - 2 );
1. why output is sometimes evaluated as 1.#QNANO in this case
2. how to test when this happens.
I forgot to add, m_alpha is a double, with typical values: 0.5, 1.5 or
2.5
Nate Eldredge
2009-06-06 17:33:26 UTC
Permalink
Post by Olumide
...
 > Perhaps then the problem is a NaN. My functions perform lots of
 > computation of the type: a^b, and occasionally, a is a very small
 > number, while b is negative, so that the result tends to 1/0 . Might
 > this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN.  The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral).  In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
Okay, here is a snip of a typical section of code that occasionally
double deltaX, deltaY, deltaZ;
initializeDeltaXYZ( ... );
double r2 = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
double output = 2 * m_alpha * pow( r2 , m_alpha - 1 ) + 4 * m_alpha *
(m_alpha - 1) * pow( deltaX , 2 ) * pow( r2 , m_alpha - 2 );
I'd suggest printing the values of all these variables (r2, m_alpha, and
all the deltas) before the computation of `output'. That will probably
bring enlightenment.
Post by Olumide
1. why output is sometimes evaluated as 1.#QNANO in this case
2. how to test when this happens.
As mentioned earlier, my guess would be that r2 comes out negative, so
you could test for that. It's also conceivable that one of the deltas
got set to a NaN somehow, depending on what initializeDeltaXYZ does.
JosephKK
2009-06-06 22:31:06 UTC
Permalink
Post by Nate Eldredge
Post by Olumide
...
 > Perhaps then the problem is a NaN. My functions perform lots of
 > computation of the type: a^b, and occasionally, a is a very small
 > number, while b is negative, so that the result tends to 1/0 . Might
 > this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN.  The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral).  In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
Okay, here is a snip of a typical section of code that occasionally
double deltaX, deltaY, deltaZ;
initializeDeltaXYZ( ... );
double r2 = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
double output = 2 * m_alpha * pow( r2 , m_alpha - 1 ) + 4 * m_alpha *
(m_alpha - 1) * pow( deltaX , 2 ) * pow( r2 , m_alpha - 2 );
I'd suggest printing the values of all these variables (r2, m_alpha, and
all the deltas) before the computation of `output'. That will probably
bring enlightenment.
Post by Olumide
1. why output is sometimes evaluated as 1.#QNANO in this case
2. how to test when this happens.
As mentioned earlier, my guess would be that r2 comes out negative, so
you could test for that. It's also conceivable that one of the deltas
got set to a NaN somehow, depending on what initializeDeltaXYZ does.
I do not see any way for r2 to ever come out negative, deltaX is a
different matter.
Nate Eldredge
2009-06-06 23:25:10 UTC
Permalink
Post by JosephKK
I do not see any way for r2 to ever come out negative, deltaX is a
different matter.
Oops, I didn't read it carefully. r2 is a sum of squares.
JosephKK
2009-06-08 06:05:30 UTC
Permalink
Post by Nate Eldredge
Post by JosephKK
I do not see any way for r2 to ever come out negative, deltaX is a
different matter.
Oops, I didn't read it carefully. r2 is a sum of squares.
Just the same i can't figure out the issue or the underlying problem
well enough to help OP much. I wonder if OP is trying to "white room"
a well known mathematical algorithm.
?
Richard Bos
2009-06-07 09:04:00 UTC
Permalink
Post by Nate Eldredge
Post by Olumide
Okay, here is a snip of a typical section of code that occasionally
double deltaX, deltaY, deltaZ;
initializeDeltaXYZ( ... );
double r2 = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
double output = 2 * m_alpha * pow( r2 , m_alpha - 1 ) + 4 * m_alpha *
(m_alpha - 1) * pow( deltaX , 2 ) * pow( r2 , m_alpha - 2 );
I'd suggest printing the values of all these variables (r2, m_alpha, and
all the deltas) before the computation of `output'. That will probably
bring enlightenment.
I agree.
Post by Nate Eldredge
Post by Olumide
1. why output is sometimes evaluated as 1.#QNANO in this case
2. how to test when this happens.
As mentioned earlier, my guess would be that r2 comes out negative,
That seems unlikely; floating point inaccuracies are one thing, but
changing the sign of a sum of (non-complex) squares to negative is
another game.
Post by Nate Eldredge
so you could test for that. It's also conceivable that one of the deltas
got set to a NaN somehow, depending on what initializeDeltaXYZ does.
Sounds more likely to me. Or that m_alpha is.

Richard
JosephKK
2009-06-06 22:14:18 UTC
Permalink
Post by Dik T. Winter
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
As much as i don't like to argue with you i expect a NaN and an
overflow indication (which may be going unhandled). But then i am
coming from the hardware side.
Nate Eldredge
2009-06-06 23:23:33 UTC
Permalink
Post by JosephKK
Post by Dik T. Winter
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
As much as i don't like to argue with you i expect a NaN and an
overflow indication (which may be going unhandled). But then i am
coming from the hardware side.
On my system (amd64, gcc, FreeBSD), print("%f\n", pow(0.0, -1.0)) prints
"inf".
JosephKK
2009-06-08 06:12:46 UTC
Permalink
Post by Nate Eldredge
Post by JosephKK
Post by Dik T. Winter
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
As much as i don't like to argue with you i expect a NaN and an
overflow indication (which may be going unhandled). But then i am
coming from the hardware side.
On my system (amd64, gcc, FreeBSD), print("%f\n", pow(0.0, -1.0)) prints
"inf".
Expected for that particular value pair. What does it get for
pow(-1e-7, -1.5)? OP may be getting this pair or not.
?
James Kuyper
2009-06-08 11:05:14 UTC
Permalink
Post by JosephKK
Post by Nate Eldredge
Post by JosephKK
Post by Dik T. Winter
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
As much as i don't like to argue with you i expect a NaN and an
overflow indication (which may be going unhandled). But then i am
coming from the hardware side.
On my system (amd64, gcc, FreeBSD), print("%f\n", pow(0.0, -1.0)) prints
"inf".
Expected for that particular value pair. What does it get for
pow(-1e-7, -1.5)? OP may be getting this pair or not.
?
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
JosephKK
2009-06-09 02:21:19 UTC
Permalink
On Mon, 08 Jun 2009 11:05:14 GMT, James Kuyper
Post by James Kuyper
Post by JosephKK
Post by Nate Eldredge
Post by JosephKK
Post by Dik T. Winter
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
As much as i don't like to argue with you i expect a NaN and an
overflow indication (which may be going unhandled). But then i am
coming from the hardware side.
On my system (amd64, gcc, FreeBSD), print("%f\n", pow(0.0, -1.0)) prints
"inf".
Expected for that particular value pair. What does it get for
pow(-1e-7, -1.5)? OP may be getting this pair or not.
?
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
Some 25 years ago i studied the IEEE-754 specification pretty
thoroughly, it left me with a deep sense of how the hardware would
operate. This came after deep understanding of two other
implementations all the way down to the gate level.
James Kuyper
2009-06-09 02:52:46 UTC
Permalink
Post by JosephKK
On Mon, 08 Jun 2009 11:05:14 GMT, James Kuyper
...
Post by JosephKK
Post by James Kuyper
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
Some 25 years ago i studied the IEEE-754 specification pretty
thoroughly, it left me with a deep sense of how the hardware would
operate. This came after deep understanding of two other
implementations all the way down to the gate level.
I asked a question with a yes or no answer; I can't translate what
you've said into either "yes" or "no", nor can I translate it into
anything resembling a claim that the restriction to "yes" and "no" is
inappropriate.

In other words, I don't see how your response can be interpreted as an
answer to my question.
JosephKK
2009-06-10 04:47:31 UTC
Permalink
On Tue, 09 Jun 2009 02:52:46 GMT, James Kuyper
Post by James Kuyper
Post by JosephKK
On Mon, 08 Jun 2009 11:05:14 GMT, James Kuyper
...
Post by JosephKK
Post by James Kuyper
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
Some 25 years ago i studied the IEEE-754 specification pretty
thoroughly, it left me with a deep sense of how the hardware would
operate. This came after deep understanding of two other
implementations all the way down to the gate level.
I asked a question with a yes or no answer; I can't translate what
you've said into either "yes" or "no", nor can I translate it into
anything resembling a claim that the restriction to "yes" and "no" is
inappropriate.
In other words, I don't see how your response can be interpreted as an
answer to my question.
Please read it as my background tells me what to expect, based on the
described values. If that conflicts with what you expect, please test
it and tell us all what happened; oops that would require assembler
programming instead of "C". Then again you may be well able to
develop those programs anyway. It is up to you to do what please.
James Kuyper
2009-06-10 10:23:04 UTC
Permalink
Post by JosephKK
On Tue, 09 Jun 2009 02:52:46 GMT, James Kuyper
Post by James Kuyper
Post by JosephKK
On Mon, 08 Jun 2009 11:05:14 GMT, James Kuyper
...
Post by JosephKK
Post by James Kuyper
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
Some 25 years ago i studied the IEEE-754 specification pretty
thoroughly, it left me with a deep sense of how the hardware would
operate. This came after deep understanding of two other
implementations all the way down to the gate level.
...
Post by JosephKK
Post by James Kuyper
In other words, I don't see how your response can be interpreted as an
answer to my question.
Please read it as my background tells me what to expect, based on the
described values. If that conflicts with what you expect, please test
it and tell us all what happened; oops that would require assembler
programming instead of "C". Then again you may be well able to
develop those programs anyway. It is up to you to do what please.
My question was about what your expectations were; I can't get the
answer to that question by writing a test program; not unless that test
program is hooked up to mind-reading hardware.

Also, this was a question about the behavior of C code, not about
assembler code, so what point would there be to writing assembler code
to determine the answer?

If the floating point hardware implements a near-equivalent of the
pow(a,n) function, that differs from the specification of pow() by
returning a NaN and an overflow indicator when a is a small positive
number, and b is a sufficiently large negative number, then the
implementation of the pow() function is required to contain whatever
additional code is needed to ensure that the behavior of the pow()
function itself meets the requirements of 7.12.1p4:

"If a floating result overflows and default rounding is in effect, or if
the mathematical result is an exact infinity from finite arguments (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; if the integer
expression math_errhandling & MATH_ERRNO is nonzero, the integer
expression errno acquires the value ERANGE; if the integer expression
math_errhandling & MATH_ERREXCEPT is nonzero, the ‘‘divide-by-zero’’
floating-point exception is raised if the mathematical result is an
exact infinity and the ‘‘overflow’’ floating-point exception is raised
otherwise."

Note: I'm pretty sure that the parts involving math_errhandling are new
to C99; I'm not sure what the corresponding wording in the C90 standard was.

The required return value in this case, HUGE_VAL, must be positive
(7.12p3), and therefore cannot be a NaN, and must (if __STDC_IEC_559__
is predefined) be positive infinity (F9p1).

There's nothing particularly unusual about a discrepancy between the
behavior of the floating point hardware and the behavior of the
corresponding standard library function. That's precisely the point of
standardizing the library, so people can write code that relies upon the
standard's guarantees, without having to worry about the details of
different hardware implementations.
JosephKK
2009-06-11 02:14:34 UTC
Permalink
On Wed, 10 Jun 2009 10:23:04 GMT, James Kuyper
Post by James Kuyper
Post by JosephKK
On Tue, 09 Jun 2009 02:52:46 GMT, James Kuyper
Post by James Kuyper
Post by JosephKK
On Mon, 08 Jun 2009 11:05:14 GMT, James Kuyper
...
Post by JosephKK
Post by James Kuyper
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
Some 25 years ago i studied the IEEE-754 specification pretty
thoroughly, it left me with a deep sense of how the hardware would
operate. This came after deep understanding of two other
implementations all the way down to the gate level.
...
Post by JosephKK
Post by James Kuyper
In other words, I don't see how your response can be interpreted as an
answer to my question.
Please read it as my background tells me what to expect, based on the
described values. If that conflicts with what you expect, please test
it and tell us all what happened; oops that would require assembler
programming instead of "C". Then again you may be well able to
develop those programs anyway. It is up to you to do what please.
My question was about what your expectations were; I can't get the
answer to that question by writing a test program; not unless that test
program is hooked up to mind-reading hardware.
It is still embedded in the quoted text above. "a NaN and an
overflow indication"
Post by James Kuyper
Also, this was a question about the behavior of C code, not about
assembler code, so what point would there be to writing assembler code
to determine the answer?
If the floating point hardware implements a near-equivalent of the
pow(a,n) function, that differs from the specification of pow() by
returning a NaN and an overflow indicator when a is a small positive
number, and b is a sufficiently large negative number, then the
implementation of the pow() function is required to contain whatever
additional code is needed to ensure that the behavior of the pow()
"If a floating result overflows and default rounding is in effect, or if
the mathematical result is an exact infinity from finite arguments (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; if the integer
expression math_errhandling & MATH_ERRNO is nonzero, the integer
expression errno acquires the value ERANGE; if the integer expression
math_errhandling & MATH_ERREXCEPT is nonzero, the ‘‘divide-by-zero’’
floating-point exception is raised if the mathematical result is an
exact infinity and the ‘‘overflow’’ floating-point exception is raised
otherwise."
Note: I'm pretty sure that the parts involving math_errhandling are new
to C99; I'm not sure what the corresponding wording in the C90 standard was.
The required return value in this case, HUGE_VAL, must be positive
(7.12p3), and therefore cannot be a NaN, and must (if __STDC_IEC_559__
is predefined) be positive infinity (F9p1).
There's nothing particularly unusual about a discrepancy between the
behavior of the floating point hardware and the behavior of the
corresponding standard library function. That's precisely the point of
standardizing the library, so people can write code that relies upon the
standard's guarantees, without having to worry about the details of
different hardware implementations.
James Kuyper
2009-06-11 09:44:58 UTC
Permalink
Post by JosephKK
On Wed, 10 Jun 2009 10:23:04 GMT, James Kuyper
Post by James Kuyper
Post by JosephKK
On Tue, 09 Jun 2009 02:52:46 GMT, James Kuyper
Post by JosephKK
On Mon, 08 Jun 2009 11:05:14 GMT, James Kuyper
...
Post by JosephKK
Post by James Kuyper
As DIk said "... if a was negative ...". So do you now agree with what
he said? Would you still expect "a NaN and an overflow indication" even
when a is not negative?
...
Post by JosephKK
Post by James Kuyper
My question was about what your expectations were; I can't get the
answer to that question by writing a test program; not unless that test
program is hooked up to mind-reading hardware.
It is still embedded in the quoted text above. "a NaN and an
overflow indication"
Since that phrase occurs in the quoted material, only as part of a
question about whether you still expected those results, an actual
answer was in fact requested; an actual answer to my question could not
be inferred from anything you've previously said in response to. I was
expecting that you were addressing the more general case, where a could
be negative, and not the actual case being discussed, where a is
actually positive.

OK, so the fact that 'a' is positive, and that pow(a,n) is therefore not
allowed to return a NaN, has not had any impact on your expectations for
the behavior of pow(a,n). Odd. Not a good way to think while writing C
or C++ code - but to each his own.
James Kuyper
2009-06-12 11:04:56 UTC
Permalink
Post by JosephKK
Post by Dik T. Winter
...
Post by Olumide
Perhaps then the problem is a NaN. My functions perform lots of
computation of the type: a^b, and occasionally, a is a very small
number, while b is negative, so that the result tends to 1/0 . Might
this explain why my function occasionally returns 1.#QNANO?
No, that would result in an infinity, not in a NAN. The only way that could
yield a NAN would be if a was negative (and with a well-designed library,
b non-integral). In all other cases a number or an infinity should be
returned (with the now common IEEE standard arithmetic).
So I suspect your a has become negative.
As much as i don't like to argue with you i expect a NaN and an
overflow indication (which may be going unhandled). But then i am
coming from the hardware side.
Should you carefully read it all again there was at least one
pow(deltaX,n) involved and delta x could have been negative. It is a
separate issue from the computation of r2.
The above comments by Olumide and Dik were about a^b, where a is
placeholder representing an arbitrary expression with a small positive
value. You're disagreeing with an assertion that generation of a NaN
implies that 'a has become negative'. How does the possibility that
deltaX might be negative justify disagreeing with that assertion? If you
were agreeing with him, I would not have expected to see words like "I
don't like to argue with you"; instead, I would have expected something
more like
Post by JosephKK
You're right - in particular, I suspect that deltaX might be negative,
in which case I would expect to see a NaN and an overflow indication
(which may be going unhandled).
Dik T. Winter
2009-06-06 01:30:22 UTC
Permalink
In article <a86cd80f-39b1-4bc7-b2ab-***@21g2000vbk.googlegroups.com> Olumide <***@web.de> writes:
...
Post by Olumide
Thanks everyone. I'm sorry I didn't express myself clearly enough. By
"too small" I mean cannot be represented by a double, thus the value
1.#QNANO (BTW, I'm using Visual Studio .NET 2003). Therefore, I meant
to ask what is the proper technique for testing the result of a
computation is not representable as a double?
You misunderstand. A NAN does not mean what you think it means. It means
either that the result is not a real number (but complex, like sqrt(-2.0))
or that the question asked makes no sense (like 0.0/0.0).

The proper way to check for it is to test with an isnan() function, if
available, otherwise the test a != a should yield true for a NAN, but
beware of compilers that are too eager in their optimisation.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Loading...