1

Inspired by this answer, I wonder why numpy.nextafter gives different results for the smallest positive float number from numpy.finfo(float).tiny and sys.float_info.min:

import numpy, sys

nextafter = numpy.nextafter(0., 1.) # 5e-324
tiny = numpy.finfo(float).tiny # 2.2250738585072014e-308
info = sys.float_info.min # 2.2250738585072014e-308

According to the documentations:

numpy.nextafter

Return the next floating-point value after x1 towards x2, element-wise.

finfo(float).tiny

The smallest positive usable number. Type of tiny is an appropriate floating point type.

sys.float_info

A structseq holding information about the float type. It contains low level information about the precision and internal representation. Please study your system's :file:float.h for more information.

Does someone have an explanation for this?

Jan Christoph Terasa
  • 5,781
  • 24
  • 34

1 Answers1

3

The documentation’s wording on this is bad; “usable” is colloquial and not defined. Apparently tiny is meant to be the smallest positive normal number.

nextafter is returning the actual next representable value after zero, which is subnormal.

Python does not rigidly specify its floating-point properties. Python implementations commonly inherit them from underlying hardware or software, and use of IEEE-754 formats (but not full conformance to IEEE-754 semantics) is common. In IEEE-754, numbers are represented with an implicit leading one bit in the significand1 until the exponent reaches its minimum value for the format, after which the implicit bit is zero instead of one and smaller values are representable only by reducing the significand instead of reducing the exponent. These numbers with the implicit leading zero are the subnormal numbers. They serve to preserve some useful arithmetic properties, such as x-y == 0 if and only if x == y. (Without subnormal numbers, two very small numbers might be different, but their even smaller difference might not be representable because it was below the exponent limit, so computing x-y would round to zero, resulting in code like if (x != y) quotient = t / (x-y) getting a divide-by-zero error.)

Note

1 “Significand” is the term preferred by experts for the fraction portion of a floating-point representation. “Mantissa” is an old term for the fraction portion of a logarithm. Mantissas are logarithmic, while significands are linear.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thank you for the answer. Probably a good read on that is (like always, forgot about it, sigh) [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). – Jan Christoph Terasa Oct 11 '18 at 14:32