Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python epsilon is not the smallest number

What does sys.float_info.epsilon return?

On my system I get:

>>> sys.float_info.epsilon
2.220446049250313e-16
>>> sys.float_info.epsilon / 2
1.1102230246251565e-16
>>> 0 < sys.float_info.epsilon / 2 < sys.float_info.epsilon
True

How is this possible?

EDIT:

You are all right, I thought epsilon does what min does. So I actually meant sys.float_info.min.

EDIT2

Everybody and especially John Kugelman, thanks for your answers!

Some playing around I did to clarify things to myself:

>>> float.hex(sys.float_info.epsilon)
'0x1.0000000000000p-52'
>>> float.hex(sys.float_info.min)
'0x1.0000000000000p-1022'
>>> float.hex(1 + a)
'0x1.0000000000001p+0'
>>> float.fromhex('0x0.0000000000001p+0') == sys.float_info.epsilon
True
>>> float.hex(sys.float_info.epsilon * sys.float_info.min)
'0x0.0000000000001p-1022'

So epsilon * min gives the number with the smallest positive significand (or mantissa) and the smallest exponent.

like image 956
Ella Sharakanski Avatar asked Apr 17 '15 21:04

Ella Sharakanski


2 Answers

epsilon is the difference between 1 and the next representable float. That's not the same as the smallest float, which would be the closest number to 0, not 1.

There are two smallest floats, depending on your criteria. min is the smallest normalized float. The smallest subnormal float is min * epsilon.

>>> sys.float_info.min
2.2250738585072014e-308
>>> sys.float_info.min * sys.float_info.epsilon
5e-324

Note the distinction between normalized and subnormal floats: min is not actually the smallest float, it's just the smallest one with full precision. Subnormal numbers cover the range between 0 and min, but they lose a lot of precision. Notice that 5e-324 has only one significant digit. Subnormals are also much slower to work with, up to 100x slower than normalized floats.

>>> (sys.float_info.min * sys.float_info.epsilon) / 2
0.0
>>> 4e-324
5e-324
>>> 5e-325
0.0

These tests confirm that 5e-324 truly is the smallest float. Dividing by two underflows to 0.

See also: What is the range of values a float can have in Python?

like image 176
John Kugelman Avatar answered Nov 11 '22 21:11

John Kugelman


You actually want sys.float_info.min ("minimum positive normalized float"), which on machine gives me .2250738585072014e-308.

epsilon is:

difference between 1 and the least value greater than 1 that is representable as a float

See the docs for more info on the fields of sys.float_info.

like image 37
Isaac Avatar answered Nov 11 '22 22:11

Isaac