Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Infinity, NaN and negative zero

A float64 can hold more than numbers: positive and negative infinity, NaN ("not a number", the result of an operation with no answer), and a zero with a sign. Floating point does not wrap on overflow; it goes to infinity.

#import "std/numeric"

'' Infinity and NaN are made by functions, not constants.
var inf = numeric.Infinity( )
var nan_ = numeric.NaN( )

'' Overflow in floating point gives infinity, not a wrapped value.
dim as float64 big = 1e308
print "1e308 * 10 is infinite: "; numeric.IsInfinite( big * 10 )
print "inf > 1e308: "; cbool( inf > big )
print "inf - inf is NaN: "; numeric.IsNaN( inf - inf )

'' A NaN equals nothing, not even itself: ask with IsNaN.
print "nan = nan: "; cbool( nan_ = nan_ )
print "IsNaN( nan ): "; numeric.IsNaN( nan_ )

'' Classify names the kind of value.
print "Classify( 0.0 ) is FP_ZERO: "; _
      cbool( numeric.Classify( 0.0 ) = numeric.FP_ZERO )
print "Classify( 1.0 ) is FP_NORMAL: "; _
      cbool( numeric.Classify( 1.0 ) = numeric.FP_NORMAL )

'' Two zeros: equal as numbers, different in the sign bit.
dim as float64 negZero = -0.0
print "-0 = 0: "; cbool( negZero = 0.0 ); _
      ", IsNegative( -0 ): "; numeric.IsNegative( negZero )
print "1 / -0 is negative infinity: "; _
      cbool( 1 / negZero = numeric.NegInfinity( ) )

'' The library passes a NaN on rather than dropping it.
print "Max( nan, 1 ) is NaN: "; numeric.IsNaN( numeric.Max( nan_, 1.0 ) )

Output

1e308 * 10 is infinite: true
inf > 1e308: true
inf - inf is NaN: true
nan = nan: false
IsNaN( nan ): true
Classify( 0.0 ) is FP_ZERO: true
Classify( 1.0 ) is FP_NORMAL: true
-0 = 0: true, IsNegative( -0 ): true
1 / -0 is negative infinity: true
Max( nan, 1 ) is NaN: true

numeric.Infinity( ), NegInfinity( ) and NaN( ) make the special values. They are functions because a constant cannot be initialised by dividing by zero.

A NaN is not equal to anything, itself included, so x = x is false for a NaN. Ask IsNaN( x ). IsInfinite, IsFinite, IsNormal and IsSubnormal complete the questions, and Classify( x ) names the kind: FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL or FP_NORMAL.

-0.0 and 0.0 are equal as numbers and differ in the sign bit, which IsNegative reads. The sign shows when you divide by it: one over negative zero is negative infinity.

The library passes a NaN on rather than dropping it: Max( NaN, 1 ) is NaN. Losing the NaN there would turn an error you could find into a wrong answer you could not.

The example prints tests of the values rather than the values. How print shows an infinity or a NaN is the runtime's choice; a test means the same on every platform.

Activities

  1. Print IsNaN( sqr( -1 ) ).
  2. Find the smallest power of ten that is infinite in a float64 with a loop and IsInfinite.