www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - nan or -nan?

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Some floating point operations produce .nan:

import std.stdio;

void main()
{
     double zero = 0;
     double infinity = double.infinity;

     writeln("any expression with nan: ", double.nan + 1);
     writeln("    zero / zero        : ", zero / zero);
     writeln("    zero x infinity    : ", zero * infinity);
     writeln("infinity / infinity    : ", infinity / infinity);
     writeln("infinity - infinity    : ", infinity - infinity);
}

Last time I checked, I think the program above would produce nan for all 
of those operations. Now some are -nan when compiled with 64-bit dmd 
2.056 on Linux:

any expression with nan: nan
     zero / zero        : -nan
     zero x infinity    : -nan
infinity / infinity    : -nan
infinity - infinity    : -nan

Is that expected? Does it matter?

Ali
Nov 15 2011
next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 16 November 2011 04:35, Ali =C7ehreli <acehreli yahoo.com> wrote:
 Some floating point operations produce .nan:

 import std.stdio;

 void main()
 {
 =A0 =A0double zero =3D 0;
 =A0 =A0double infinity =3D double.infinity;

 =A0 =A0writeln("any expression with nan: ", double.nan + 1);
 =A0 =A0writeln(" =A0 =A0zero / zero =A0 =A0 =A0 =A0: ", zero / zero);
 =A0 =A0writeln(" =A0 =A0zero x infinity =A0 =A0: ", zero * infinity);
 =A0 =A0writeln("infinity / infinity =A0 =A0: ", infinity / infinity);
 =A0 =A0writeln("infinity - infinity =A0 =A0: ", infinity - infinity);
 }

 Last time I checked, I think the program above would produce nan for all =

 those operations. Now some are -nan when compiled with 64-bit dmd 2.056 o=

 Linux:

 any expression with nan: nan
 =A0 =A0zero / zero =A0 =A0 =A0 =A0: -nan
 =A0 =A0zero x infinity =A0 =A0: -nan
 infinity / infinity =A0 =A0: -nan
 infinity - infinity =A0 =A0: -nan

 Is that expected? Does it matter?

 Ali

This behaviour may be due to the libraries rather than the compiler. But whether the bit that controls signed-ness is on or off, doesn't stop the value being NaN. So I would not give much concern to the result. --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
Nov 17 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Iain Buclaw:

 This behaviour may be due to the libraries rather than the compiler.

In any case there is a bug to be found an fixed.
 But whether the bit that controls signed-ness is on or off, doesn't
 stop the value being NaN.  So I would not give much concern to the
 result.

It's a NaN, but floating point designers have given a sign to NaNs for a (small) purpose. In a numerics-oriented language as D you don't want to ignore that purpose, you want to get right the full semantics of floating point numbers, on 64 bits too. So I suggest to add this problem in Bugzilla. Bye, bearophile
Nov 17 2011
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/17/2011 3:57 PM, bearophile wrote:
 It's a NaN, but floating point designers have given a sign to NaNs for a
(small) purpose.

What is that purpose?
Nov 17 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 On 11/17/2011 3:57 PM, bearophile wrote:
 It's a NaN, but floating point designers have given a sign to NaNs for a
(small) purpose.

What is that purpose?

I didn't know the answer, so I've done a short research (finding texts like this: http://grouper.ieee.org/groups/754/email/msg03893.html ), I have found that languages usually ignore the sign of the NaNs (while the sign of zero has some purposes). Producing the same bit patterns for 32 and 64 bit compilers is useful for output binary consistency for comparisons, but comparing floating point values bitwise is usually a not so wise thing to do. So I think there is no need to put this in Bugzilla. Thank you for your question, bye, bearophile
Nov 17 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/17/2011 5:29 PM, bearophile wrote:
 Walter:

 On 11/17/2011 3:57 PM, bearophile wrote:
 It's a NaN, but floating point designers have given a sign to NaNs for a
 (small) purpose.

What is that purpose?

I didn't know the answer, so I've done a short research (finding texts like this: http://grouper.ieee.org/groups/754/email/msg03893.html ), I have found that languages usually ignore the sign of the NaNs (while the sign of zero has some purposes). Producing the same bit patterns for 32 and 64 bit compilers is useful for output binary consistency for comparisons, but comparing floating point values bitwise is usually a not so wise thing to do. So I think there is no need to put this in Bugzilla.

There is a NaN "payload" in the significand which it is polite to preserve, though no program has ever been observed to make use of it. The sign bit is not part of the payload. Requiring preservation of the sign bit means that one could not negate a floating point value without checking for NaN, which would be a significant performance penalty. It's not a bug.
Nov 17 2011
parent reply Paul D. Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
Walter Bright Wrote:

 On 11/17/2011 5:29 PM, bearophile wrote:
 Walter:

 On 11/17/2011 3:57 PM, bearophile wrote:
 It's a NaN, but floating point designers have given a sign to NaNs for a
 (small) purpose.

What is that purpose?

I didn't know the answer, so I've done a short research (finding texts like this: http://grouper.ieee.org/groups/754/email/msg03893.html ), I have found that languages usually ignore the sign of the NaNs (while the sign of zero has some purposes). Producing the same bit patterns for 32 and 64 bit compilers is useful for output binary consistency for comparisons, but comparing floating point values bitwise is usually a not so wise thing to do. So I think there is no need to put this in Bugzilla.

There is a NaN "payload" in the significand which it is polite to preserve, though no program has ever been observed to make use of it. The sign bit is not part of the payload. Requiring preservation of the sign bit means that one could not negate a floating point value without checking for NaN, which would be a significant performance penalty. It's not a bug.

From the Decimal Arithmetic Specification (http://speleotrove.com/decimal/decarith.pdf): "All special values may have a sign, as for finite numbers. The sign of an infinity is significant (that is, it is possible to have both positive and negative infinity), and the sign of a NaN has no meaning, although it may be considered part of the diagnostic information." In addition, the specification, based on IEEE 754 and IEEE 854, makes a distinction between a "signaling NaN" (sNaN) and a "quiet NaN" (qNaN). D doesn't make this distinction. In essence all D NaNs are signaling. The specification includes the quiet NaN for "a value representing undefined results... which does not cause an Invalid operation condition". In practice, this is the result of an arithmetic operation with a NaN (quiet or signaling) as an operand. (An sNaN as an operand will still raise an invalid operation flag, but if this doesn't cause an exception, the result of the operation will be a qNaN.) I don't know if this will be of any more value than the NaN payload, but there it is. Paul p.s.
Nov 18 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/18/2011 1:32 PM, Paul D. Anderson wrote:
 From the Decimal Arithmetic Specification
 (http://speleotrove.com/decimal/decarith.pdf):

 "All special values may have a sign, as for finite numbers. The sign of an
 infinity is significant (that is, it is possible to have both positive and
 negative infinity), and the sign of a NaN has no meaning, although it may be
 considered part of the diagnostic information."

Having no meaning means it is legitimate to not be concerned if the sign is toggled.
 In addition, the specification, based on IEEE 754 and IEEE 854, makes a
 distinction between a "signaling NaN" (sNaN) and a "quiet NaN" (qNaN). D
 doesn't make this distinction. In essence all D NaNs are signaling.

Signaling vs quiet is not set by the sign bit, but by the most significant bit of the significand. D does make use of signaling NaNs as they are what are generated for uninitialized data. Other than that, the payloads are not used. I did support them in Digital Mars C, but nobody used them.
Nov 18 2011
parent Don <nospam nospam.com> writes:
On 19.11.2011 01:22, Walter Bright wrote:
 On 11/18/2011 1:32 PM, Paul D. Anderson wrote:
 From the Decimal Arithmetic Specification
 (http://speleotrove.com/decimal/decarith.pdf):

 "All special values may have a sign, as for finite numbers. The sign
 of an
 infinity is significant (that is, it is possible to have both positive
 and
 negative infinity), and the sign of a NaN has no meaning, although it
 may be
 considered part of the diagnostic information."

Having no meaning means it is legitimate to not be concerned if the sign is toggled.

I'm not sure about that. They may simply be saying that it has no "physical" meaning, without saying that it has no meaningful semantics. The behaviour is a bit strange, because x86 does define the sign of NaN for all operations. If the sign doesn't have reliable semantics, we probably shouldn't be printing it. It just causes confusion. Personally, I think it would make more sense to only print the sign if you're also printing the payload. Maybe print -nan for %a format, but not for %f and %e.
Nov 21 2011
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/18/2011 11:54 AM, Iain Buclaw wrote:
 On 17 November 2011 23:57, bearophile<bearophileHUGS lycos.com>  wrote:
 Iain Buclaw:

 This behaviour may be due to the libraries rather than the compiler.

In any case there is a bug to be found an fixed.

When I said libraries, I meant system libraries - ie: glibc. I seem to recall it being added a few years back. If you are on an older system, or Windows, you may not see the signedness at all.

That makes sense: I've moved from CentOS 4 to Ubuntu 11. Ali
Nov 18 2011
prev sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 17 November 2011 23:57, bearophile <bearophileHUGS lycos.com> wrote:
 Iain Buclaw:

 This behaviour may be due to the libraries rather than the compiler.

In any case there is a bug to be found an fixed.

When I said libraries, I meant system libraries - ie: glibc. I seem to recall it being added a few years back. If you are on an older system, or Windows, you may not see the signedness at all. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Nov 18 2011