Python numpy машина 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.float32class. Кто-нибудь может помочь с изменением функции?


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% уверенным, первый обеспечивает "стандартную" точность Python для врожденных чисел с плавающей запятой, а второй - точность чисел с плавающей запятой numpy?
Чарли Паркер

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это тип, специфичный для numpy, и у 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дает ноль?
Steve Tjoa 08

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

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

29
Этот ответ не требует каких-либо знаний о Python или внутреннем устройстве numpy.
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

кстати, ваша функция будет повышаться, NameErrorесли условие whileбудет выполнено при первой проверке, поэтому, вероятно, имеет смысл сделать это machine_epsilon = machine_epsilon_last = func(1)в первом операторе
Азат Ибраков
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.