91

Is there a standard value for (or method for obtaining) epsilon in Python? I need to compare floating point values and want to compare against the smallest possible difference.

In C++ there's a function provided numeric_limits::epsilon( ) which gives the epsilon value for any given data type. Is there an equivalent in Python?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
thornate
  • 4,902
  • 9
  • 39
  • 43
  • 8
    When comparing floats, the magnitude of the values will affect the epsilon. – John La Rooy Mar 02 '12 at 05:38
  • 1
    Consider also that error in values can propagate across operations. The field "Numerical Analysis" is devoted to the study of this. [This](http://floating-point-gui.de/errors/propagation/) site also provides some good rules to follow. – Casey Kuball May 09 '12 at 20:03
  • As an example to people's comment above, `1e300-(1e300-1e200)` return `0.0`, where the actual difference must be 10^200. – THN Sep 28 '18 at 01:57

5 Answers5

155

The information is available in sys.float_info, which corresponds to float.h in C99.

>>> import sys
>>> sys.float_info.epsilon
2.220446049250313e-16
strcat
  • 5,376
  • 1
  • 27
  • 31
38

As strcat posted, there is sys.float_info.epsilon.

But don't forget the pitfalls of using it as an absolute error margin for floating point comparisons. E.g. for large numbers, rounding error could exceed epsilon.

If you think you need a refresher, the standard reference is David Goldberg's What Every Computer Scientist Should Know About Floating-Point Arithmetic, or for a simpler review you can check out The Floating Point Guide.

Community
  • 1
  • 1
Ergwun
  • 12,579
  • 7
  • 56
  • 83
16

If you cannot find a function to do that, remember that the algorithm to calculate the machine epsilon is very easy (you can test with your favourite programming language).E.g, for python:

eps = 1.0
while eps + 1 > 1:
    eps /= 2
eps *= 2
print("The machine epsilon is:", eps)

In my case, I got:

The machine epsilon is: 2.220446049250313e-16

s.ouchene
  • 1,682
  • 13
  • 31
9

Surprised nobody mentioned this here; I think many people would use numpy.finfo( type(variable) ).eps instead. Or .resolution if it is to assess precision.

Note that finfo is only for floating point types, and that it also works with Python's own float type (i.e. not restricted to numpy's types). The equivalent for integer types is iinfo, though it does not contain precision information (because, well, why would it?).

Jonathan H
  • 7,591
  • 5
  • 47
  • 80
  • 8
    Disagreed about the "most people": not everyone uses NumPy. If you want the epsilon for *Python*'s `float`, use `sys.float_info`; it would be strange to use NumPy just for that. If you're after values for *NumPy* types (`np.float32`, `np.float64`, etc.), then use `numpy.finfo`. – Mark Dickinson Mar 03 '18 at 09:48
  • 1
    Changed the wording. To clarify though, `np.finfo(float)` _does_ work, but I agree that if you never use numpy, then it would be overkill to install the package just for that. – Jonathan H Mar 03 '18 at 17:36
  • 4
    Right, but `np.finfo(float)` is a bit misleading, since NumPy [immediately converts](https://github.com/numpy/numpy/blob/6914bb41f0fb3c1ba500bae4e7d671da9536786f/numpy/core/getlimits.py#L378) the `float` to `np.float64`, and then reports details for that. So it's reporting on a NumPy type again, not on Python's `float`. (Though admittedly, it's overwhelmingly likely that `float` and `np.float64` are the same format: they're both using C doubles under the hood.) – Mark Dickinson Mar 03 '18 at 18:39
4

The following worked for me as well:

>>> import math
>>> math.ulp(1.0)
2.220446049250313e-16
Rúben Dias
  • 336
  • 2
  • 9