Концепции с плавающей точкой в ​​Python - PullRequest
3 голосов
/ 25 декабря 2009

Почему -22/10 возвращает -3 в python. Любые указания по этому поводу будут полезны для меня.

Ответы [ 5 ]

10 голосов
/ 25 декабря 2009

Потому что это целочисленное деление по умолчанию. А целочисленное деление округляется до минус бесконечности. Взгляните:

>>> -22/10
-3
>>> -22/10.0
-2.2000000000000002

Positive:

>>> 22/10
2
>>> 22/10.0
2.2000000000000002

Что касается кажущейся "неточности" с плавающей запятой, это отличная статья для чтения: Почему вычисления с плавающей запятой настолько неточны?

5 голосов
/ 25 декабря 2009

PEP 238 , «Смена оператора подразделения», я думаю, хорошо объясняет проблемы. Вкратце: когда Python был спроектирован, он принял «усеченное» значение для / между целыми числами, просто потому, что большинство других языков программирования делали это с тех пор, как в 1957 году был запущен первый компилятор FORTRAN (имя из всех прописных букв и все ;-) (Одним широко распространенным языком, который не принял это значение, используя / для получения результата с плавающей запятой и div для усечения, был Pascal).

В 2001 году было решено, что этот выбор не является оптимальным (цитируя PEP: «Это делает выражения, ожидающие плавающие или сложные результаты подверженными ошибкам, когда целые числа не ожидаются, но возможны в качестве входных данных»), и переключиться на использование новый оператор // для запроса деления с усечением и изменения значения / для получения результата с плавающей запятой («истинное деление»).

Вы можете явно запросить это поведение, поместив оператор

from __future__ import division

в начале модуля (переключение командной строки -Q на интерпретатор python также может управлять поведением деления). В отсутствие такого «импорта из будущего» (и использования переключателя командной строки) Python 2.x для всех значений x всегда использует «классическое деление» (т. Е. / усекается между int с).

Python 3, однако, всегда использует «истинное деление» (/ между int s производит float).

Обратите внимание на любопытное следствие (в Python 3) ...:

>>> from fractions import Fraction
>>> Fraction(1/2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/fractions.py", line 100, in __new__
    raise TypeError("argument should be a string "
TypeError: argument should be a string or a Rational instance

, поскольку / создает float, это не приемлемо в качестве аргумента для Fraction (в противном случае точность может быть молча потеряна) Вы должны использовать строку или передать числитель и знаменатель в качестве отдельных аргументов:

>>> Fraction(1, 2)
Fraction(1, 2)
>>> Fraction('1/2')
Fraction(1, 2)

gmpy использует другой, более терпимый подход к построению mpq s, его эквивалент Python 3 Fraction s ...:

>>> import gmpy
>>> gmpy.mpq(1/2)
mpq(1,2)

В частности (см. Строки 3168 и далее в источник ), gmpy использует дерево Штерна-Броко , чтобы получить «наилучшее практическое приближение» аргумента с плавающей точкой в ​​качестве рационального (конечно, эта может маскировать потерю точности).

5 голосов
/ 25 декабря 2009

По умолчанию текущие версии Python 2.x (я не уверен насчет 3.x) дают целочисленный результат для любого арифметического оператора, когда оба операнда являются целыми числами. Однако есть способ изменить это поведение.

from __future__ import division
print(22/10)

Выходы

2.2000000000000002

Конечно, более простой способ - просто сделать один из операндов плавающим, как описано в предыдущих двух ответах.

2 голосов
/ 25 декабря 2009

Это происходит потому, что операция целочисленного деления возвращает число, которое при умножении на делитель дает максимально возможное целое число, не превышающее число, которое вы поделили.

Именно поэтому 22/10 дает 2: 10 * 2 = 20, что является наибольшим целым числом, кратным 10, не больше 20.

Когда это становится отрицательным, ваша операция становится -22/10. Ваш результат -3. Применяя ту же логику, что и в предыдущем случае, мы видим, что 10 * -3 = -30, что является наибольшим целым кратным 10, не превышающим -20.

Вот почему вы получаете немного неожиданный ответ при работе с отрицательными числами.

Надеюсь, что поможет

2 голосов
/ 25 декабря 2009

Потому что вы делаете целочисленное деление. Если вместо этого вы введете -22,0 / 10, вы получите правильный результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...