python numpy machine epsilon


103

Я намагаюся зрозуміти, що таке машинний епсилон. Згідно з Вікіпедією, його можна обчислити так:

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

Однак він підходить лише для чисел з подвійною точністю. Мені цікаво змінити його, щоб підтримувати також єдині точні числа. Я читав, що numpy можна використовувати, особливо numpy.float32класу. Чи може хто-небудь допомогти із зміною функції?


8
Ця функція є достатньо загальною для роботи з усіма точністю. Просто передайте numpy.float32як аргумент функції!
Девід Цвікер

Відповіді:


192

Найпростіший спосіб отримати машинний епсилон для даного типу поплавця - це використовувати np.finfo():

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

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

3
щоб бути впевненим на 100%, перший забезпечує пітон "стандартну" точність вроджених плавців, а другий - точність плавців нумі?
Чарлі Паркер

2
зауважте, що стандартна точність numpy дорівнює 64 (у 64-бітному комп'ютері): >>> print(np.finfo(np.float).eps) = 2.22044604925e-16 і >>> print(np.finfo(np.float64).eps) = 2.22044604925e-16
Чарлі Паркер

2
@CharlieParker я міг би використати np.floatнатомість, оскільки це лише псевдонім вбудованого Python float. Плавці Python мають 64-бітний (C double) майже на всіх платформах. floatі np.float64тому зазвичай мають рівнозначну точність, і для більшості цілей ви можете використовувати їх взаємозамінно. Однак вони не є однаковими - np.float64це специфічний для нумеру тип, а np.float64скаляр має різні методи для нативного floatскаляра. Як і слід було очікувати, np.float32це 32-бітний поплавок.
ali_m

92

Ще один простий спосіб отримати епсилон:

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

4
Так, і чому 8./3 - 5./3 - 1врожайність -eps, і 4./3 - 1./3 - 1врожайність дорівнює нулю, і 10./3 - 7./3 - 1врожайність?
Стів Тьоа

20
О, відповідь тут, проблема 3: rstudio-pubs-static.s3.amazonaws.com/… В основному, якщо відняти двійкове представлення 4/3 від 7/3, ви отримаєте визначення машинного епсилона. Тому я припускаю, що це має стосуватися будь-якої платформи.
Стів Тьоа

13
Це надто езотерична відповідь, яка вимагає занадто багато знань про Python та numpyвнутрішніх справ, коли існує numpyфункція, щоб знайти епсилон.
Ольга Ботвінник

29
Ця відповідь не вимагає жодних знань про внутрішні проблеми Python або nummy.
GuillaumeDufay

5
Дійсно, він стверджує, що читачеві відомо про роботу Python на комп'ютерах, які не використовують обчислення базових 3.
kokociel

17

Це вже буде працювати, як вказував Давид!

>>> 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 ваша функція підвищиться, NameErrorякщо умова whileбуде задоволена при першій перевірці, тому це, мабуть, має сенс зробити machine_epsilon = machine_epsilon_last = func(1)в першому виписці
Азат Ібраков
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.