Числа: int, float, Decimal и арифметика
Арифметика
| Оператор | Действие | Пример | Результат |
|---|---|---|---|
+ - * |
сложение, вычитание, умножение | 7 * 3 |
21 |
/ |
деление (всегда float) | 7 / 2, 6 / 2 |
3.5, 3.0 |
// |
целочисленное деление (вниз) | 7 // 2 |
3 |
% |
остаток | 7 % 2 |
1 |
** |
степень | 2 ** 10 |
1024 |
-x, abs(x) |
минус, модуль | abs(-5) |
5 |
print(7 / 2, 7 // 2, 7 % 2, 2 ** 10)
print(divmod(17, 5)) # (3, 2) — частное и остаток сразу
print(2 ** 0.5) # корень через степень
print(10 ** 20, 2 ** 200) # int — произвольной длины
Приоритет
** → унарный - → *, /, //, % → +, - → сравнения → not → and → or.
print(2 + 3 * 4) # 14
print(-2 ** 2) # -4: сначала степень, потом минус
print((-2) ** 2) # 4
print(2 ** 3 ** 2) # 512: степень правоассоциативна, 2 ** (3 ** 2)
Деление отрицательных чисел
// округляет к минус бесконечности, а не к нулю, как в C или Java. Поэтому -7 // 2 == -4, а -7 % 2 == 1. Инвариант всегда выполняется: a == (a // b) * b + a % b.
for a, b in [(7, 2), (-7, 2), (7, -2), (-7, -2)]:
print(f"{a:>3} // {b:>2} = {a // b:>3} {a:>3} % {b:>2} = {a % b:>2}")
float и его погрешность
float хранит число в двоичном виде (стандарт IEEE 754, 64 бита). Десятичные дроби вроде 0.1 в двоичной системе — бесконечные, поэтому хранятся приближённо.
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(f"{0.1:.20f}") # как 0.1 хранится на самом деле
import math
print(math.isclose(0.1 + 0.2, 0.3)) # правильное сравнение float
print(float("inf"), float("nan"), float("nan") == float("nan"))
Деньги во float не храните
Ошибки накапливаются: сумма тысячи платежей по 0.1 не будет ровно 100. Для денег используйте целые копейки (int) или decimal.Decimal.
Округление
print(round(3.14159, 2)) # 3.14
print(round(2.5), round(3.5)) # 2 4 — банковское округление: к чётному
print(round(2.675, 2)) # 2.67, а не 2.68: 2.675 хранится как 2.67499999...
import math
print(math.floor(-2.5), math.ceil(-2.5), math.trunc(-2.5), int(-2.5))
| Функция | Что делает | 2.7 |
-2.7 |
|---|---|---|---|
int(), math.trunc() |
отбросить дробную часть | 2 | -2 |
math.floor() |
вниз | 2 | -3 |
math.ceil() |
вверх | 3 | -2 |
round() |
к ближайшему (половина — к чётному) | 3 | -3 |
Decimal и Fraction
from decimal import Decimal, ROUND_HALF_UP
from fractions import Fraction
print(Decimal("0.1") + Decimal("0.2")) # 0.3 — точно
print(Decimal(0.1)) # из float — уже с погрешностью!
price = Decimal("2.675")
print(price.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)) # 2.68
print(Fraction(1, 3) + Fraction(1, 6)) # 1/2 — точные дроби
Decimal создают из строки
Decimal("0.1") — точное значение, Decimal(0.1) — уже испорченный float.
Системы счисления и биты
print(0b1010, 0o17, 0xFF) # литералы: двоичный, восьмеричный, шестнадцатеричный
print(bin(10), oct(15), hex(255)) # обратно в строку
print(int("1010", 2), int("ff", 16)) # из строки с основанием
print(1_000_000) # подчёркивания для читаемости
# побитовые операции
a, b = 0b1100, 0b1010
print(bin(a & b), bin(a | b), bin(a ^ b), bin(~a), bin(a << 2), bin(a >> 2))
print((42).bit_length(), (255).bit_count())
Побитовые операции встречаются в задачах на собеседованиях: проверка чётности n & 1, степень двойки n & (n - 1) == 0, XOR для поиска единственного непарного числа.
nums = [4, 1, 2, 1, 2]
result = 0
for x in nums:
result ^= x # парные числа взаимно уничтожаются: x ^ x == 0
print(result) # 4
Модуль math
import math
print(math.pi, math.e)
print(math.sqrt(16), math.isqrt(17)) # isqrt — целый корень
print(math.gcd(12, 18), math.lcm(4, 6))
print(math.factorial(10), math.comb(5, 2), math.perm(5, 2))
print(math.log(100, 10), math.log2(1024))
Итог
/всегда float,//округляет вниз,%имеет знак делителя.- float неточен: сравнивайте через
math.isclose, деньги храните вintилиDecimal("..."). roundиспользует банковское округление.- Литералы
0b,0o,0x, функцииbin/oct/hex,int(s, base); побитовые& | ^ ~ << >>.
Практика решено 0 из 6
Чему равно выражение?
| 2 | -3 | 3.5 | 1 | 2.0 | |
|---|---|---|---|---|---|
7 // 2 - 1 |
|||||
-7 // 2 + 1 |
|||||
7 / 2 |
|||||
-7 % 2 |
|||||
4 / 2 |
Что выведет print(0.1 + 0.2 == 0.3)?
Напишите функцию split_bill(total, people), которая возвращает кортеж из двух целых чисел:
сколько рублей платит каждый поровну и сколько рублей остаётся (остаток).
Например, split_bill(1000, 3) → (333, 1).
Какие тесты проверяют код (3)
assert split_bill(1000, 3) == (333, 1) assert split_bill(900, 3) == (300, 0) assert split_bill(5, 10) == (0, 5)
divmod(a, b) возвращает (a // b, a % b) одной операцией.
def split_bill(total, people):
return total // people, total % people
Что вернёт round(2.5) в Python 3?
Напишите функцию almost_equal(a, b), которая возвращает True, если два float равны
с учётом погрешности вычислений. Используйте math.isclose.
Какие тесты проверяют код (3)
assert almost_equal(0.1 + 0.2, 0.3) is True assert almost_equal(1.0, 1.1) is False assert almost_equal(1e10 + 0.0001, 1e10) is True
import math
def almost_equal(a, b):
return math.isclose(a, b)
Чему равно int("ff", 16)? (число)
Войдите, чтобы отмечать пройденные уроки.