python mesin numpy epsilon

103

Saya mencoba memahami apa itu mesin epsilon. Menurut Wikipedia, itu dapat dihitung sebagai berikut:

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

Namun, ini hanya cocok untuk angka presisi ganda. Saya tertarik untuk memodifikasinya untuk mendukung juga angka presisi tunggal. Saya membaca bahwa numpy dapat digunakan, terutama di numpy.float32kelas. Adakah yang bisa membantu dengan memodifikasi fungsi?

Bob
sumber
8
Fungsi itu cukup umum untuk bekerja dengan semua presisi. Berikan saja numpy.float32sebagai argumen ke fungsi!
David Zwicker

Jawaban:

192

Cara yang lebih mudah untuk mendapatkan mesin epsilon untuk tipe float tertentu adalah dengan menggunakan np.finfo():

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

print(np.finfo(np.float32).eps)
# 1.19209e-07
ali_m
sumber
3
hanya untuk menjadi 100% yakin, yang pertama memberikan presisi "standar" python untuk pelampung bawaan sedangkan yang kedua adalah ketepatan pelampung numpy?
Charlie Parker
2
perhatikan bahwa akurasi standar numpy adalah 64 (di komputer 64 bit): >>> print(np.finfo(np.float).eps) = 2.22044604925e-16 dan >>> print(np.finfo(np.float64).eps) = 2.22044604925e-16
Charlie Parker
2
@CharlieParker Saya dapat menggunakan np.floatsebagai gantinya, karena ini hanya alias dari bawaan Python float. Float Python 64-bit (C double) di hampir semua platform. floatdan np.float64karena itu biasanya memiliki presisi yang setara, dan untuk sebagian besar tujuan Anda dapat menggunakannya secara bergantian. Namun keduanya tidak identik - np.float64merupakan tipe khusus numpy, dan np.float64skalar memiliki metode yang berbeda dengan floatskalar asli . Seperti yang Anda harapkan, np.float32ini adalah float 32-bit.
ali_m
92

Cara lain yang mudah untuk mendapatkan epsilon adalah:

In [1]: 7./3 - 4./3 -1
Out[1]: 2.220446049250313e-16
Ullen
sumber
4
Ya, dan mengapa 8./3 - 5./3 - 1menghasilkan -eps, dan 4./3 - 1./3 - 1menghasilkan nol, dan 10./3 - 7./3 - 1menghasilkan nol?
Steve Tjoa
20
Ah, jawabannya ada di sini, Soal 3: rstudio-pubs-static.s3.amazonaws.com/… Pada dasarnya, jika Anda mengurangi representasi biner 4/3 dari 7/3, Anda mendapatkan definisi mesin epsilon. Jadi saya kira ini harus berlaku untuk platform apa pun.
Steve Tjoa
13
Ini adalah jawaban yang terlalu esoterik yang membutuhkan terlalu banyak pengetahuan tentang Python dan numpyinternal ketika ada numpyfungsi yang ada untuk menemukan epsilon.
Olga Botvinnik
29
Jawaban ini tidak memerlukan pengetahuan tentang Python atau bagian dalam numpy.
GuillaumeDufay
5
Memang, ini menegaskan bahwa pembaca mengetahui tentang Python yang berjalan pada komputer yang tidak menggunakan komputasi base-3 yang mendasarinya.
kokociel
17

Itu sudah akan berhasil, seperti yang ditunjukkan 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
Claudiu
sumber
btw fungsi Anda akan naik NameErrorjika kondisi dalam whileakan dipenuhi pada pemeriksaan pertama, jadi mungkin masuk akal untuk dilakukan machine_epsilon = machine_epsilon_last = func(1)dalam pernyataan pertama
Azat Ibrakov