Python numpy máquina epsilon


103

Estoy tratando de entender qué es la máquina épsilon. Según Wikipedia, se puede calcular de la siguiente manera:

def machineEpsilon(func=float):
    machine_epsilon = func(1)
    while func(1)+func(machine_epsilon) != func(1):
        machine_epsilon_last = machine_epsilon
        machine_epsilon = func(machine_epsilon) / func(2)
    return machine_epsilon_last

Sin embargo, solo es adecuado para números de doble precisión. Estoy interesado en modificarlo para admitir también números de precisión simple. Leí que se puede usar numpy, particularmente numpy.float32class. ¿Alguien puede ayudar a modificar la función?


8
Esa función es lo suficientemente general como para trabajar con todas las precisiones. ¡Simplemente pase a numpy.float32como argumento a la función!
David Zwicker

Respuestas:


192

Una forma más fácil de obtener el épsilon de la máquina para un tipo de flotante dado es usar np.finfo():

print(np.finfo(float).eps)
# 2.22044604925e-16

print(np.finfo(np.float32).eps)
# 1.19209e-07

3
sólo para estar 100% seguro, el primero proporciona la precisión "estándar" de python de los flotadores innatos, mientras que el segundo la precisión de los flotadores de numpy.
Charlie Parker

2
tenga en cuenta que la precisión estándar de Numpy es 64 (en una computadora de 64 bits): >>> print(np.finfo(np.float).eps) = 2.22044604925e-16 y >>> print(np.finfo(np.float64).eps) = 2.22044604925e-16
Charlie Parker

2
@CharlieParker podría haber usado en su np.floatlugar, ya que es solo un alias del incorporado de Python float. Los flotadores de Python son de 64 bits (C double) en casi todas las plataformas. floaty, np.float64por lo tanto, suelen tener una precisión equivalente, y para la mayoría de los propósitos puede usarlos indistintamente. Sin embargo, no son idénticos: np.float64es un tipo específico de muchos, y un np.float64escalar tiene métodos diferentes a un floatescalar nativo . Como era de esperar, np.float32es un flotante de 32 bits.
ali_m

92

Otra forma fácil de obtener épsilon es:

In [1]: 7./3 - 4./3 -1
Out[1]: 2.220446049250313e-16

4
Sí, ¿y por qué 8./3 - 5./3 - 1rinde -epsy 4./3 - 1./3 - 1rinde cero y 10./3 - 7./3 - 1rinde cero?
Steve Tjoa

20
Ah, la respuesta está aquí, Problema 3: rstudio-pubs-static.s3.amazonaws.com/… Básicamente, si resta la representación binaria de 4/3 de 7/3, obtiene la definición de máquina épsilon. Así que supongo que esto debería ser válido para cualquier plataforma.
Steve Tjoa

13
Esta es una respuesta demasiado esotérica que requiere demasiado conocimiento de Python y aspectos numpyinternos cuando hay una numpyfunción existente para encontrar el épsilon.
Olga Botvinnik

29
Esta respuesta no requiere ningún conocimiento de Python o componentes internos de Numpy.
GuillaumeDufay

5
De hecho, afirma que el lector está al tanto de que Python se ejecuta en computadoras que no usan computación base 3 subyacente.
kokociel

17

¡Ya funcionará, como señaló David!

>>> def machineEpsilon(func=float):
...     machine_epsilon = func(1)
...     while func(1)+func(machine_epsilon) != func(1):
...         machine_epsilon_last = machine_epsilon
...         machine_epsilon = func(machine_epsilon) / func(2)
...     return machine_epsilon_last
... 
>>> machineEpsilon(float)
2.220446049250313e-16
>>> import numpy
>>> machineEpsilon(numpy.float64)
2.2204460492503131e-16
>>> machineEpsilon(numpy.float32)
1.1920929e-07

Por cierto, su función aumentará NameErrorsi la condición whilese cumple en la primera verificación, por lo que probablemente tenga sentido hacerlo machine_epsilon = machine_epsilon_last = func(1)en la primera declaración
Azat Ibrakov
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.