В этой главе рассматриваются операции с числами в языке Python. В Python поддерживаются целые числа (такие, как −1, 5 или 2000) и числа с плавающей точкой (приближенное компьютерное представление таких чисел, как 0,333, 0,5 или −1000,234); они позволяют легко выполнять числовые операции. Изначально в Python предусмотрена поддержка операций сложения, вычитания, умножения, деления, возведения в степень, вычисления остатка и многих других операций!
В отличие от других языков, в Python существуют только объекты — это относится и к числам. Целые числа относятся к классу int:
>>> type(1)
<class 'int'>
Числа с плавающей точкой относятся к классу float:
>>> type(2.0)
<class 'float'>
Точность представления нецелых чисел ограничена. Пользователь должен сам определить, достаточно ли ее для его текущих вычислений. Во внутреннем представлении чисел с плавающей точкой Python использует двоичное представление (соответствующее стандарту IEEE 754 для чисел с плавающей точкой). У чисел с плавающей точкой существует определенный порог точности, поэтому возможна погрешность округления. Собственно, разработчик всегда должен ожидать, что вычисления выполняются с погрешностью округления. (Если вам потребуется более высокая точность, модуль decimal предоставляет более точную, хотя и более медленную реализацию.)
Рассмотрим точность представления на простом примере. Что происходит при выполнении простой на первый взгляд операции вычитания?
>>> print(1.01 - .99)
0.020000000000000018
СОВЕТ
Если вам захочется больше узнать о числах с плавающей точкой и их представлении в памяти компьютера, в Википедии имеется более подробная информация по теме.
Python REPL может использоваться как простейший калькулятор. Чтобы сложить два целых числа, введите выражение:
>>> 2 + 6
8
ПРИМЕЧАНИЕ
В этом примере результат не связывается с переменной. Для вывода результата простейшего вычисления на терминал этого может быть достаточно. Если результат вдруг понадобится вам позднее, интерпретатор Python сохраняет последний результат в переменной с именем _:
>>> 2 + 6
8
>>> result = _
>>> result
8
При сложении двух целых чисел будет получено целое число. Аналогичным образом можно сложить два числа с плавающей точкой:
>>> .4+.01
0.41000000000000003
Этот пример снова показывает, почему при работе с числами с плавающей точкой необходима осторожность: операции могут приводить к потере точности (настоящий результат равен 0,41).
А что произойдет при сложении целого числа с числом с плавающей точкой?
>>> 6 + .2
6.2
Python решает, что, поскольку вы складываете целое число с числом с плавающей точкой, вам нужна арифметическая операция с плавающей точкой. В данном случае Python автоматически преобразует 6 в число с плавающей точкой перед тем, как складывать его с .2. Python возвращает результат в формате с плавающей точкой.
ПРИМЕЧАНИЕ
Если в операции используются два числовых операнда, преобразование обычно работает правильно. Для операций, в которых задействовано целое число и число с плавающей точкой, целое число преобразуется в формат с плавающей точкой.
ПРИМЕЧАНИЕ
Преобразования между строками и числами не выполняются для большинства математических операций. У правила есть два исключения: оператор форматирования строки и оператор умножения.
При использовании % со строкой в левой части (левый операнд) и любым объектом (включая числа) в правой части (правый операнд) Python выполняет операцию форматирования:
>>> print('num: %s' % 2)
num: 2
Если левый операнд является строкой, то при применении оператора умножения * Python выполняет повторение:
>>> 'Python!' * 2
'Python!Python!'
>>> '4' * 2
'44'
ПРИМЕЧАНИЕ
С классами int и float могут выполняться явные преобразования (несмотря на внешнее сходство с функциями, в действительности это классы):
>>> int(2.3)
2
>>> float(3)
3.0
Вычитание имеет много общего с умножением. При вычитании двух целых чисел или двух чисел с плавающей точкой будет получено целое число или число с плавающей точкой соответственно. Для смешанных числовых типов перед вычитанием выполняется преобразование операндов:
>>> 2 - 6
-4
>>> .25 - 0.2
0.04999999999999999
>>> 6 - .2
5.8
Во многих языках программирования символ * (звездочка) используется для умножения. Вероятно, вы и сами догадаетесь, что произойдет при умножении двух целых чисел:
>>> 6 * 2
12
Если вы внимательно читали, то уже знаете, что происходит при умножении двух чисел с плавающей точкой:
>>> .25 * 12.0
3.0
А при смешанных типах в произведении будет получен результат с плавающей точкой:
>>> 4 * .3
1.2
Результат с плавающей точкой в этих примерах выглядит правильным. Тем не менее будьте внимательны и помните о проблемах с погрешностью представления — не стоит полагать, что вам всегда будет везти.
В Python (как и во многих языках) знак / обозначает деление:
>>> 12 / 4
3.0
В Python 3 также решена проблема, которую в предыдущих версиях Python многие считали дефектом. Результат деления двух целых чисел является числом с плавающей точкой:
>>> 3 / 4
0.75
Прежде в Python выполнялось целочисленное деление. Если вам нужен именно такой вариант поведения, используйте оператор //. Какое целое число использует Python? Результат округления в меньшую сторону:
>>> 3 // 4
0
Оператор % вычисляет остаток от целочисленного деления. Например, с его помощью можно проверить число на четность (или узнать, были ли обработаны 1000 элементов списка):
# Остаток от деления 4 на 3
>>> 4 % 3
1
>>> 3 % 2 # нечетно, если результат равен 1
1
>>> 4 % 2 # четно, если результат равен 0
0
СОВЕТ
Будьте внимательны при использовании оператора % с отрицательными числами. Поведение оператора изменяется в зависимости от того, какой из операндов отрицателен. Понятно, что при отсчете в обратном направлении остаток должен повторяться с определенной периодичностью:
>>> 3 % 3
0
>>> 2 % 3
2
>>> 1 % 3
1
>>> 0 % 3
0
Какой результат должен быть получен при вычислении -1 % 3? Так как отсчет ведется в обратном направлении, результат снова должен быть равен 2:
>>> -1 % 3
2
Но если изменить знак делителя, происходит нечто странное:
>>> -1 % -3
-1
Python гарантирует, что знак результата совпадает со знаком делителя (или равен 0). Чтобы окончательно запутать вас, еще один пример:
>>> 1 % -3
-2
Мораль: пожалуй, вам не стоит вычислять остаток с отрицательным делителем — только если вы твердо уверены в том, что вам действительно нужно именно это.
Python также поддерживает оператор возведения в степень ** (две звездочки). Если вы хотите возвести 4 в квадрат (4 — основание, 2 — показатель степени), это делается так:
>>> 4 ** 2
16
Результаты операции возведения в степень обычно стремительно увеличиваются. Допустим, вы хотите возвести 10 в 100-ю степень:
>>> 10 ** 100
10000000000000000000000000000000000000
00000000000000000000000000000000000000
0000000000000000000000000
Для хранения целых чисел программам требуется определенный объем памяти. Так как целые числа обычно относительно невелики, Python оптимизирует затраты памяти, чтобы избежать ее непроизводительного расходования. Во внутренней реализации «системные» целые числа могут быть преобразованы в длинные целые для хранения больших чисел. Python 3 делает это за вас автоматически.
Представьте шкалу пружинных весов. Если вы всегда взвешиваете мелкие предметы, вам будут удобны весы с короткой шкалой. Если вы торгуете песком, вероятно, песок будет удобно насыпать в мешки, чтобы с ними было удобнее работать. Вы будете держать под рукой небольшие мешки, чтобы использовать их для взвешивания. Но если время от времени вам приходится взвешивать большие предметы, выходящие за короткую шкалу, придется доставать большие весы и большой мешок. Было бы неразумно использовать большой мешок и большие весы для многих мелких предметов.
Точно так же Python старается оптимизировать память для хранения целых чисел, ориентируясь на небольшие размеры. Если целое число не помещается в малый блок памяти (мешок), Python преобразует его в большое целое. На самом деле это желательное поведение, потому что в некоторых средах ошибка переполнения приводит к аварийному завершению программы (или PacMan отказывается переходить на уровни выше 255, потому что счетчик уровня хранится в виде 8-разрядного числа).
ПРИМЕЧАНИЕ
Python включает модуль operator с функциями для основных математических операций. В частности, он пригодится вам при использовании таких расширенных возможностей Python, как лямбда-функции или генераторы списков:
>>> import operator
>>> operator.add(2, 4) # same as 2 + 4
6
При выполнении математических вычислений не все операции выполняются слева направо. Например, операции сложения и вычитания выполняются после операций умножения и деления. Компьютеры работают по тем же правилам. Если вы хотите, чтобы операции сложения (или вычитания) выполнялись в первую очередь, используйте круглые скобки для обозначения порядка операций:
>>> 4 + 2 * 3
10
>>> (4 + 2) * 3
18
Как следует из примера, выражение в круглых скобках вычисляется в первую очередь.
Справочный раздел REPL весьма полезен. В нем имеется тема NUMBERMETHODS, объясняющая, как работают все числовые операции.
В Python имеется встроенная поддержка основных математических операций. Разумеется, язык поддерживает сложение, вычитание, умножение и деление. Кроме того, доступны операции возведения в степень и вычисления остатка. Если вам понадобится управлять порядком выполнения операций, заключите ту операцию, которая должна выполняться первой, в круглые скобки. Если вам нужно провести простые вычисления, вместо запуска приложения-калькулятора можно выполнить их в Python. Возможности языка более чем достаточны для большинства задач.
1. В эту неделю вы спали 6,2, 7, 8, 5, 6,5, 7,1 и 8,5 часа. Вычислите среднюю продолжительность сна в часах.
2. Делится ли число 297 без остатка на 3?
3. Чему равен результат возведения 2 в десятую степень?
4. В Википедии високосный год определяется следующим образом:
«…високосным оставался год, номер которого кратен четырем, но исключение делалось для тех, которые были кратны 100. Такие годы были високосными только тогда, когда делились еще и на 400… Так, годы 1700, 1800 и 1900 не являются високосными, так как они кратны 100 и не кратны 400. Годы 1600 и 2000 — високосные».
Напишите код Python, который определяет, являются ли високосными годы 1800, 1900, 1903, 2000 и 2002.