floor(-1e-14 % 2)
Out[1]: 1.0
floor(-1e-16 % 2)
Out[2]: 2.0
Я понимаю, что -1e-16
может быть слишком близко от 0
, но ни в коем случае результат пола после % 2
операции должны быть 2 (0 или 1)!Ошибка в функции пола
floor(-1e-14 % 2)
Out[1]: 1.0
floor(-1e-16 % 2)
Out[2]: 2.0
Я понимаю, что -1e-16
может быть слишком близко от 0
, но ни в коем случае результат пола после % 2
операции должны быть 2 (0 или 1)!Ошибка в функции пола
Это не ошибка в floor.Check результат %
In [61]: -1e-16 % 2
Out[61]: 2.0
In [62]: -1e-14 % 2
Out[62]: 1.99999999999999
Вы можете прочитать What Every Computer Scientist Should Know About Floating-Point Arithmetic, чтобы узнать больше о том, почему %
ведет себя так.
Модуль decimal обеспечивает поддержку десятичной арифметики с плавающей запятой. Он обладает несколькими преимуществами по сравнению с типом данных типа foat. Поэтому для точной математики по плавающей запятой значения
sys.float_info
Для получения более подробной информации о поплавковом типе можно использовать sys.flaot_info
.
sys.float_info.dig
показывает максимальное количество десятичных цифр, которое может быть точно представлено в поплавке; Для расчетов, которые включают значения с большим количеством цифр вы не можете ожидать точных результатов с заданной точностью
Это то, что я получил
In [217]: import sys
In [218]: sys.float_info.dig
Out[218]: 15
Я не вижу причины для downvote. Это точно отвечает на вопрос OP (хотя лучшим ответом будет и тот, который объясняет, почему «%» работает так). –
@JohnColeman У меня нет downvote, но это * * причуда в 'floor'. Почему 'floor (1.9)' return 1 и 'floor (1.9999)' return 1 but 'floor (1.9999999999999999999999)' return 2? – Tagc
@Tagc, вероятно, это потому, что https://docs.python.org/2/tutorial/floatingpoint.html –
Вы правы, что результат -1e-16
не должен быть 2.0
, но поплавки странные, и печально менее точные. Спецификация %
оператора states:
В то время как абс (х% у) < абс (у) истинно математически, для поплавков оно не может быть истинным численно из-за округления. Например, и предполагая платформу, на которой плавающий Python является номером двойной точности IEEE 754, для того, чтобы -1e-100% 1e100 имели тот же знак, что и 1e100, вычисленный результат равен -1e-100 + 1e100, что численно точно равным 1e100. Функция math.fmod() возвращает результат, знак которого соответствует знаку первого аргумента, и поэтому возвращает -1e-100 в этом случае. Какой подход более подходит, зависит от приложения.
. Я понимаю проблемы, когда мы достигаем предельного предела выделения 0.0, а не 0.0, т. Е. Когда мы находимся в окрестности 1,18 × 10-38, но 1е-16 на порядки выше ! –
Действительные числа @YvesSurrel, которые точно представляют собой поплавки, распределены равномерно. Просто потому, что заданный 'x' вблизи 0 является представимым, не означает, что' 2 + x' есть. '2 + -1e-16' соответствует' 2.0'. –
Хорошая точка! Верно, что (2.0 + 1e-16) - 2.0 составляет ровно 0,0 –
Похоже, проблема с оператором '%', чем ошибка в 'floor'. – khelwood
Согласно моему Python 3.3.1, '-1e-16% 2' является' 2' –
Предположительно '% 2' перемещает' -1e-16' в положительный диапазон (по существу добавляя '2'), и, следовательно, число округляется, и вы получаете странный результат. Ну что ж. Плавающие точки. – khelwood