Машина Epsilon в Python
Пособие, которое я сейчас изучаю (я новичок), говорит:
"Числа, которые отличаются меньше, чем машинный эпсилон, численно одинаковы"
С помощью Python машинный epsilon для значений float можно получить, набрав
eps = numpy.finfo(float).eps
Теперь, если я проверяю
1 + eps/10 != 1
Я получаю False.
Но если я проверяю
0.1 + eps/10 != 0.1
Я получаю True.
Последнее логическое выражение оказывается ложным, если я делю eps на 100.
Итак, как работает машина epsilon? Документация Python просто говорит
"Наименьшее представимое положительное число, такое, что 1.0 + eps!= 1.0. Тип eps - подходящий тип с плавающей точкой.
Спасибо заранее.
Ответы
Ответ 1
Числа с плавающей запятой имеют определенную точность, до нескольких знаков после запятой в научной нотации. Чем больше число, тем больше наименее значимая цифра в этом представлении и, следовательно, тем больше "эпсилон", который может способствовать этому числу.
Таким образом, epsilon относится к числу, к которому он добавлен, что фактически указано в документации, которую вы указали: "... такое, что 1.0 + eps!= 1.0". Если "ссылочный" номер меньше, например, один порядок магнита, то и eps также меньше.
Если бы это было не так, вы не могли бы рассчитать вообще с номерами, меньшими, чем eps (2.2e-16
в моем случае).
Ответ 2
В этом случае вы действительно не хотите np.finfo
. То, что вам нужно, - это np.spacing
, который вычисляет расстояние между входом и следующим наибольшим числом, которое может быть точно представлено.
По существу, np.spacing
вычисляет "eps" для любого заданного числа. Он использует тип данных числа (собственные поплавки python - это 64-битные поплавки), поэтому np.float32
или np.float16
даст другой ответ, чем 64-битный float.
Например:
import numpy as np
print 'Float64, 1.0 -->', np.spacing(1.0)
print 'Float64, 1e12 -->', np.spacing(1e12)
print 'Float64, 1e-12 -->', np.spacing(1e-12)
print ''
print 'Float32, 1.0 -->', np.spacing(np.float32(1.0))
print 'Float32, 1e12 -->', np.spacing(np.float32(1e12))
print 'Float32, 1e-12 -->', np.spacing(np.float32(1e-12))
Что дает:
Float64, 1.0 --> 2.22044604925e-16
Float64, 1e12 --> 0.0001220703125
Float64, 1e-12 --> 2.01948391737e-28
Float32, 1.0 --> 1.19209e-07
Float32, 1e12 --> 65536.0
Float32, 1e-12 --> 1.0842e-19