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.