Skip to content

Output of np.finfo is misleading #16252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rk-mlu opened this issue May 15, 2020 · 2 comments · Fixed by #16253
Closed

Output of np.finfo is misleading #16252

rk-mlu opened this issue May 15, 2020 · 2 comments · Fixed by #16253

Comments

@rk-mlu
Copy link
Contributor

rk-mlu commented May 15, 2020

It appears to me that either the documentation of np.finfo() is somewhat misleading or the functions returns a wrong result for the parameter tiny.

According to the doc of np.finfo() tiny is

the smallest positive usable number.

According to the script below that is not true.

I am not sure if this is really a bug. I suspect that tiny in np.finfo() actually refers to the smallest normalized floating-point number. However, the IEEE 754 standard also includes subnormal floating-point numbers. This is also implemented in np.float64. The smallest positive subnormal is 2**(-1022)*2**(-52). See Wiki.

It may make sense to distinguish between these two classes of floats since the latter does not have the full resolution of up to 16 decimals, but may have considerably less precision. However, from my point of view np.float64 supports subnormals and they are usable numbers. Hence either the documentation should be adapted or a further attribute may be added to np.finfo such as tiny_norm vs. tiny_subn.

Reproducing code example:

import numpy as np

print('Output of np.finfo(np.float64)')
print(np.finfo(np.float64))

# value for tiny equals
tiny = 2**(-1022)

# define some smaller number
x = np.zeros(3)
x[0] = 2**(-1023)
x[1] = 2**(-1074)
x[2] = 2**(-1075) # underflow occurs

print('Print decimal representations of tiny and some smaller floats:')
print('2**(-1022) = Tiny = ', tiny)
print('2**(-1023) =', x[0])
print('2**(-1074) =', x[1])
print('2**(-1075) =', x[2])

Output:

Output of np.finfo(np.float64)
Machine parameters for float64
---------------------------------------------------------------
precision =  15   resolution = 1.0000000000000001e-15
machep =    -52   eps =        2.2204460492503131e-16
negep =     -53   epsneg =     1.1102230246251565e-16
minexp =  -1022   tiny =       2.2250738585072014e-308
maxexp =   1024   max =        1.7976931348623157e+308
nexp =       11   min =        -max
---------------------------------------------------------------

Print decimal representations of tiny and some smaller floats:
2**(-1022) = Tiny =  2.2250738585072014e-308
2**(-1023) = 1.1125369292536007e-308
2**(-1074) = 5e-324
2**(-1075) = 0.0

Numpy/Python version information:

1.16.2 3.7.5 (default, Apr 19 2020, 20:18:17)
[GCC 9.2.1 20191008]

@seberg
Copy link
Member

seberg commented May 15, 2020

@rk-mlu you are right, that is the smallest non-subnormal number, we should maybe add that as a comment in the docs. I suppose we could add a tiny_subnormal, not sure its typically relevant since you quickly start losing precision at that point.

Can you make a PR suggesting a change in the documentation? That would be great!

@rk-mlu
Copy link
Contributor Author

rk-mlu commented May 15, 2020

@seberg No problem, I will write up a comment for the documentation.

rk-mlu added a commit to rk-mlu/numpy that referenced this issue May 15, 2020
This commit adds a note to the documentation of finfo clarifying that
the attribute `tiny` does not represent the smallest positive usable
number. Instead it refers to the smallest positive number with there
being no leading 0's in the mantisse (normalized floating point number).
Alternatively, `tiny` represents the smallest positive floating point
number with full precision. The smallest positive subnormal floating
point number is typically orders of magnitudes smaller, but has reduced
precision since leading 0's in the mantisse are used to allow smaller
exponents than indicated by `minexp`.

The commit also adds a brief clarification to the docstring of machar.

Closes numpy#16252
seberg pushed a commit that referenced this issue May 18, 2020
This commit adds a note to the documentation of finfo clarifying that
the attribute `tiny` does not represent the smallest positive usable
number. Instead it refers to the smallest positive number with there
being no leading 0's in the mantisse (normalized floating point number).
Alternatively, `tiny` represents the smallest positive floating point
number with full precision. The smallest positive subnormal floating
point number is typically orders of magnitudes smaller, but has reduced
precision since leading 0's in the mantisse are used to allow smaller
exponents than indicated by `minexp`.

The commit also adds a brief clarification to the docstring of machar.

Closes #16252

Co-authored-by: Anirudh Subramanian <anirudh2290@apache.org>
Co-authored-by: Ross Barnowski <rossbar@berkeley.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants