python numpy machine epsilon


103

Sto cercando di capire cos'è la macchina epsilon. Secondo Wikipedia, può essere calcolato come segue:

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

Tuttavia, è adatto solo per numeri a doppia precisione. Mi interessa modificarlo per supportare anche numeri a precisione singola. Ho letto che numpy può essere utilizzato, in particolare di numpy.float32classe. Qualcuno può aiutare a modificare la funzione?


8
Questa funzione è abbastanza generale da funzionare con tutte le precisioni. Passa semplicemente un numpy.float32come argomento alla funzione!
David Zwicker

Risposte:


192

Un modo più semplice per ottenere la macchina epsilon per un dato tipo di float è usare np.finfo():

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

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

3
giusto per essere sicuri al 100%, il primo fornisce la precisione "standard" di Python dei float innati mentre il secondo la precisione dei float di numpy?
Charlie Parker

2
nota che la precisione standard di numpy è 64 (in un computer a 64 bit): >>> print(np.finfo(np.float).eps) = 2.22044604925e-16 e >>> print(np.finfo(np.float64).eps) = 2.22044604925e-16
Charlie Parker

2
@CharlieParker avrei potuto usare np.floatinvece, dato che è solo un alias del builtin di Python float. I float Python sono a 64 bit (C double) su quasi tutte le piattaforme. floate np.float64quindi di solito hanno una precisione equivalente e per la maggior parte degli scopi è possibile utilizzarli in modo intercambiabile. Tuttavia non sono identici: np.float64è un tipo specifico di numpy e uno np.float64scalare ha metodi diversi da uno floatscalare nativo . Come ti aspetteresti, np.float32è un float a 32 bit.
ali_m

92

Un altro modo semplice per ottenere epsilon è:

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

4
Sì, e perché 8./3 - 5./3 - 1produce -epse 4./3 - 1./3 - 1produce zero e 10./3 - 7./3 - 1produce zero?
Steve Tjoa

20
Ah, la risposta è qui, Problema 3: rstudio-pubs-static.s3.amazonaws.com/… Fondamentalmente, se sottrai la rappresentazione binaria di 4/3 da 7/3, ottieni la definizione di macchina epsilon. Quindi suppongo che questo dovrebbe valere per qualsiasi piattaforma.
Steve Tjoa

13
Questo è troppo esoterico per una risposta che richiede troppa conoscenza di Python e degli numpyinterni quando c'è una numpyfunzione esistente per trovare epsilon.
Olga Botvinnik

29
Questa risposta non richiede alcuna conoscenza di Python o di numpy internals.
GuillaumeDufay

5
Infatti, afferma che il lettore è a conoscenza del fatto che Python è in esecuzione su computer che non utilizzano il calcolo in base 3 sottostante.
kokociel

17

Funzionerà già, come ha sottolineato 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

btw la tua funzione aumenterà NameErrorse la condizione in whilesarà soddisfatta al primo controllo, quindi probabilmente ha senso farlo machine_epsilon = machine_epsilon_last = func(1)nella prima istruzione
Azat Ibrakov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.