2017-01-26 2 views
2
floor(-1e-14 % 2) 
Out[1]: 1.0 

floor(-1e-16 % 2) 
Out[2]: 2.0 

Я понимаю, что -1e-16 может быть слишком близко от 0, но ни в коем случае результат пола после % 2 операции должны быть 2 (0 или 1)!Ошибка в функции пола

+1

Похоже, проблема с оператором '%', чем ошибка в 'floor'. – khelwood

+0

Согласно моему Python 3.3.1, '-1e-16% 2' является' 2' –

+0

Предположительно '% 2' перемещает' -1e-16' в положительный диапазон (по существу добавляя '2'), и, следовательно, число округляется, и вы получаете странный результат. Ну что ж. Плавающие точки. – khelwood

ответ

6

Это не ошибка в 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 
+0

Я не вижу причины для downvote. Это точно отвечает на вопрос OP (хотя лучшим ответом будет и тот, который объясняет, почему «%» работает так). –

+0

@JohnColeman У меня нет downvote, но это * * причуда в 'floor'. Почему 'floor (1.9)' return 1 и 'floor (1.9999)' return 1 but 'floor (1.9999999999999999999999)' return 2? – Tagc

+0

@Tagc, вероятно, это потому, что https://docs.python.org/2/tutorial/floatingpoint.html –

2

Вы правы, что результат -1e-16 не должен быть 2.0, но поплавки странные, и печально менее точные. Спецификация % оператора states:

В то время как абс (х% у) < абс (у) истинно математически, для поплавков оно не может быть истинным численно из-за округления. Например, и предполагая платформу, на которой плавающий Python является номером двойной точности IEEE 754, для того, чтобы -1e-100% 1e100 имели тот же знак, что и 1e100, вычисленный результат равен -1e-100 + 1e100, что численно точно равным 1e100. Функция math.fmod() возвращает результат, знак которого соответствует знаку первого аргумента, и поэтому возвращает -1e-100 в этом случае. Какой подход более подходит, зависит от приложения.

+0

. Я понимаю проблемы, когда мы достигаем предельного предела выделения 0.0, а не 0.0, т. Е. Когда мы находимся в окрестности 1,18 × 10-38, но 1е-16 на порядки выше ! –

+0

Действительные числа @YvesSurrel, которые точно представляют собой поплавки, распределены равномерно. Просто потому, что заданный 'x' вблизи 0 является представимым, не означает, что' 2 + x' есть. '2 + -1e-16' соответствует' 2.0'. –

+0

Хорошая точка! Верно, что (2.0 + 1e-16) - 2.0 составляет ровно 0,0 –

Смежные вопросы