Марк Лутц - Изучаем Python, Четвертое издание (1184811), страница 45
Текст из файла (страница 45)
Оператор // выполняет деление с округлениемвниз, усекая дробную часть и возвращая целочисленный результат, еслиоба операнда являются целыми числами, и вещественный – если хотя быодин операнд является вещественным числом.•• В версии 2.6 оператор / выполняет операцию классического деления, производя целочисленное деление с усечением дробной части, если оба операндаявляются целыми числами, и вещественное деление (с сохранением дробной части) – в противном случае. Оператор // выполняет деление с округлением вниз и действует так же, как и в версии 3.0, выполняя делениес усечением дробной части, если оба операнда являются целыми числами,и деление с округлением вниз, если хотя бы один из операндов является вещественным числом.Ниже эти два оператора демонстрируются в действии в версиях 3.0 и 2.6:C:\misc> C:\Python30\python>>>>>> 10 / 4# Изменился в версии 3.0: сохраняет дробную часть2.5>>> 10 // 4 # В версии 3.0 действует так же: усекает дробную часть2>>> 10 / 4.0 # В версии 3.0 действует так же: сохраняет дробную часть2.5>>> 10 // 4.0 # В версии 3.0 действует так же: округляет вниз2.0C:\misc> C:\Python26\python>>>168Глава 5.
Числа>>>2>>>2>>>2.5>>>2.010 / 410 // 410 / 4.010 // 4.0Обратите внимание, что в версии 3.0 тип результата операции // по-прежнемузависит от типов операндов: если хотя бы один из операндов является вещественным числом, результат также будет вещественным числом; в противномслучае результат будет целым числом. Несмотря на то, что это может показаться похожим на поведение оператора /, зависящее от типа операндов, в версиях 2.����������������������������������������������������������������X���������������������������������������������������������������, которое послужило побудительной причиной его изменения в версии 3.0, нужно признать, что тип возвращаемого значения является гораздоменее существенным – в сравнении с разницей в самих возвращаемых значениях.
Кроме того, оператор // был сохранен с целью обеспечения обратной совместимости для программ, которые используют операцию целочисленногоделения с усечением (она используется намного чаще, чем можно было бы подумать), которая должна возвращать целочисленный результат, когда оба операнда являются целыми числами.Поддержка обеих версий PythonХотя поведение оператора / различно в версиях 2.6 и 3.0, тем не менее, существует возможность обеспечить поддержку обеих версий в своем программномкоде. Если в программе требуется выполнить операцию целочисленного деления с усечением, используйте оператор // в обеих версиях, 2.6 и 3.0. Если программе требуется получить вещественный результат при делении целых чиселбез усечения дробной части используйте в операторе / функцию float, чтобыгарантировать, что один из операндов всегда будет вещественным числом, прииспользовании версии 2.6:X = Y // Z# Всегда усекает, для целочисленных операндов всегда возвращает# целочисленный результат в обеих версиях, 2.6 и 3.0X = Y / float(Z) # Гарантирует вещественное деление с сохранением дробной# части в обеих версиях, 2.6 и 3.0Кроме того, в версии 2.6 режим истинного деления, который используетсяв версии 3.0, можно включить, если вместо использования преобразованияfloat импортировать модуль __future__:C:\misc> C:\Python26\python>>> from __future__ import division # Включает поведение “/” как версии 3.0>>> 10 / 42.5>>> 10 // 42Округление вниз и усечение дробной частиСуществует один очень тонкий момент: оператор // обычно называют оператором деления с усечением, но более точно было бы называть его оператором деления с округлением результата вниз – он округляет результат до ближайшего169Числа в действиименьшего целого значения, то есть до целого числа, расположенного ниже истинного результата.
Округление вниз – это совсем не то же самое, что усечениедробной части, – это обстоятельство приобретает значение при работе с отрицательными числами. Разницу можно наглядно продемонстрировать, обратившись к модулю math (прежде чем использовать модуль, его необходимо импортировать, но подробнее об этом мы поговорим позже):>>>>>>2>>>-3>>>2>>>-2import mathmath.floor(2.5)math.floor(-2.5)math.trunc(2.5)math.trunc(-2.5)При выполнении операции деления в действительности усечение выполняетсятолько в случае положительного результата, поскольку для положительныхчисел усечение и округление вниз – суть одно и то же; в случае отрицательногорезультата выполняется округление вниз (в действительности и в том и в другом случае выполняется округление вниз, но в случае положительных чиселокругление вниз дает тот же эффект, что и усечение дробной части).
Ниже приводятся примеры деления в версии 3.0:C:\misc> c:\python30\python>>> 5 / 2, 5 / -2(2.5, -2.5)>>> 5 // 2, 5 // -2# Округление вниз: результат 2.5 округляется до 2,(2, -3)# а -2.5 округляется до -3>>> 5 / 2.0, 5 / -2.0(2.5, -2.5)>>> 5 // 2.0, 5 // -2.0 # То же относится и к вещественному делению,(2.0, -3.0)# только результат имеет вещественный типДеление в версии 2.6 выполняется точно так же, только результат действияоператора / отличается:C:\misc> c:\python26\python>>> 5 / 2, 5 / -2# Отличается от результата в версии 3.0(2, -3)>>> 5 // 2, 5 // -2# Эта и следующие операции дают одинаковый результат(2, -3)# в обеих версиях, 2.6 и 3.0>>> 5 / 2.0, 5 / -2.0(2.5, -2.5)>>> 5 // 2.0, 5 // -2.0(2.0, -3.0)Если требуется реализовать усечение дробной части независимо от знака, результат вещественного деления всегда можно передать функции math.trunc независимо от используемой версии Python (кроме того, взгляните на функциюround, которая обладает сходной функциональностью):C:\misc> c:\python30\python>>> import math>>> 5 / -2-2.5# Сохранит дробную часть170Глава 5.
Числа>>> 5 // -2-3>>> math.trunc(5 / -2)-2C:\misc> c:\python26\python>>> import math>>> 5 / float(-2)-2.5>>> 5 / -2, 5 // -2(-3, -3)>>> math.trunc(5 / float(-2))-2# Округлит результат вниз# Вместо округления будет выполнено усечение# Сохранит дробную часть в версии 2.6# Округлит результат вниз в версии 2.6# Вместо округления будет выполнено# усечение в версии 2.6Почему усечение так важно?Для тех, кто использует Python 3.0, ниже приводится пример, позволяющийпонять принцип действия операторов деления:>>> (5 / 2), (5 / 2.0), (5 / -2.0), (5 / -2)# Истинное деление(2.5, 2.5, -2.5, -2.5)>>> (5 // 2), (5 // 2.0), (5 // -2.0), (5 // -2) # Деление с округлением вниз (2,2.0, -3.0, -3)>>> (9 / 3), (9.0 / 3), (9 // 3), (9 // 3.0)# Оба оператора(3.0, 3.0, 3, 3.0)В версии 2.6 операторы деления действуют, как показано ниже:>>> (5 / 2), (5 / 2.0), (5 / -2.0), (5 / -2)# Классическое деление(2, 2.5, -2.5, -3)>>> (5 // 2), (5 // 2.0), (5 // -2.0), (5 // -2) # Деление с округлением вниз(2, 2.0, -3.0, -3)>>> (9 / 3), (9.0 / 3), (9 // 3), (9 // 3.0)# Оба оператора(3, 3.0, 3, 3.0)Хотя это еще и не проявилось в полной мере, тем не менее, можно предположить, что такое поведение оператора / в версии 3.0 может отрицательно сказаться на правильной работе большого числа программ.
Благодаря опыту, приобретенному при работе с языком C�����������������������������������������������������������������������������, многие программисты интуитивно полагаются на то, что операция деления целых чисел будет выполнена с усечением,и пройдет какое-то время, прежде чем они научатся пользоваться оператором// в таких случаях. Рассмотрите простой пример цикла while в главе 13 и соответствующее упражнение в конце четвертой части книги, которые иллюстрируют программный код, на котором может сказаться это изменение в поведении оператора /.
Кроме того, обратите внимание на специальную команду from,использованную в этом разделе; подробнее она будет рассмотрена в главе 24.Точность представления целых чиселОперация деления может немного отличаться в разных версиях Python, нов основе своей она является достаточно стандартной. А теперь добавим немногоэкзотики.
Как уже упоминалось выше, в Python 3.0 поддерживаются целыечисла неограниченной точности:>>> 999999999999999999999999999999 + 11000000000000000000000000000000Числа в действии171В версии Python�������������������������������������������������������������������������������������������������������������������������� 2.6 для представления длинных целых чисел имеется отдельный тип, но интерпретатор автоматически преобразует обычное целое числов длинное целое, если его значение превысит величину, которая может бытьпредставлена обычным целым числом.