Тип float и функция float() в Python
float в Python - это тип для дробных чисел и одноименная функция, которая превращает строку или целое число в число с плавающей точкой. В статье разобраны правила преобразования, ошибки ValueError и OverflowError, особенности хранения дробей в памяти и способы корректно сравнивать и округлять результаты. Отдельно показано, когда вместо float лучше взять Decimal или Fraction.

Содержание статьи
Синтаксис функции float()
Вызов float(x) возвращает новое число с плавающей точкой. Аргумент необязателен: без него функция вернет 0.0. Строго говоря, float это класс, а вызов создает его экземпляр, но в обиходе говорят "функция float".
print(float()) # 0.0
print(float(25)) # 25.0
print(float(True)) # 1.0
print(float("3.14")) # 3.14
print(float("1e-3")) # 0.001
print(type(7 / 2)) # <class 'float'>| Аргумент | Результат | Пример |
|---|---|---|
| Целое число | То же значение с дробной частью .0 | float(10) → 10.0 |
| Число float | То же число | float(11.22) → 11.22 |
| Строка с числом | Разобранное число | float(" -13.5 ") → -13.5 |
| Строка inf, nan | Бесконечность или "не число" | float("-Infinity") → -inf |
| Decimal, Fraction | Ближайшее значение float | float(Fraction(1, 4)) → 0.25 |
| None, список | Ошибка TypeError | float(None) |
Своему классу можно добавить поддержку float(): достаточно определить метод __float__, который возвращает число. Дробный результат появляется и без явного вызова: оператор деления / всегда возвращает float, даже для 4 / 2.
Преобразование строк
Строка должна содержать только запись числа. Пробелы и переносы строк по краям отбрасываются, знак + или - допустим, как и экспоненциальная запись 2.5e3. С Python 3.6 разрешены подчеркивания между цифрами: float("1_000.5") вернет 1000.5. Слова inf, infinity и nan распознаются в любом регистре.
print(float(" -24.45\n")) # -24.45
print(float("InFiNiTy")) # inf
print(float("nan")) # nan
float("3,14") # ValueError: could not convert string to float: '3,14'
float("12 руб") # ValueErrorВвод дробного числа с клавиатуры
Функция input() всегда возвращает строку, поэтому ее результат оборачивают во float(). Пользователи часто вводят запятую вместо точки, ее стоит заменить заранее, а некорректный ввод перехватить исключением.
def read_float(prompt):
while True:
raw = input(prompt).strip().replace(",", ".")
try:
return float(raw)
except ValueError:
print("Нужно число, например 12.5")
price = read_float("Цена: ")
print(price * 2)Как float хранится в памяти
В CPython float занимает 64 бита и устроен по стандарту IEEE 754 двойной точности. Это дает 15-17 значащих десятичных цифр и диапазон примерно до 1.8 × 10308. Точные границы хранит sys.float_info.
Большинство десятичных дробей в двоичной системе бесконечны, как 1/3 в десятичной. Число 0.1 хранится приближенно, и ошибки при сложении накапливаются:
import sys
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
print(sys.float_info.max) # 1.7976931348623157e+308
print(sys.float_info.epsilon) # 2.220446049250313e-16
print(1e308 * 10) # inf
print(float(10 ** 400)) # OverflowError: int too large to convert to floatЭто свойство двоичной арифметики, а не ошибка Python: тот же результат дают C, Java и JavaScript. При умножении результат за пределами диапазона превращается в inf, а при переводе слишком большого целого функция выбрасывает OverflowError.
Сравнение и округление
Из-за погрешностей дробные числа нельзя сравнивать оператором ==. Используйте math.isclose(): она проверяет, что числа отличаются меньше допуска. Для сравнения с нулем задайте абсолютный допуск abs_tol, так как относительный рядом с нулем не работает.
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
print(math.isclose(1e-12, 0, abs_tol=1e-9)) # True
print(round(2.675, 2)) # 2.67, а не 2.68
print(f"{2 / 3:.3f}") # 0.667
print(int(-7.9), math.floor(-7.9)) # -7 -8Функция round() работает с двоичным значением: 2.675 на деле хранится как 2.67499999..., поэтому округляется вниз. Кроме того, ровно половину она округляет к четному: round(2.5) дает 2. Для вывода на экран удобнее форматирование f"{x:.2f}", оно не меняет само число. Все способы разобраны в статье про округление чисел, а функции floor(), ceil() и trunc() описаны на странице модуля math.
Методы объекта float
У дробного числа есть несколько полезных методов, о которых редко пишут в учебниках.
x.is_integer()возвращает True, если дробная часть равна нулю:(3.0).is_integer()даст True.x.as_integer_ratio()возвращает точную дробь, которой равно число:(0.5).as_integer_ratio()вернет(1, 2).x.hex()иfloat.fromhex(s)переводят число в шестнадцатеричную запись и обратно без потери точности.
Значение nan не равно ничему, даже самому себе, поэтому проверять его нужно функцией math.isnan(x), а бесконечность функцией math.isinf(x). Значения nan часто появляются в данных из таблиц и после деления бесконечностей.
Когда float не подходит
Для денег, бухгалтерии и любых расчетов, где важна каждая копейка, используют тип Decimal из модуля decimal. Он хранит десятичные цифры точно и позволяет выбрать режим округления. Для точной работы с обыкновенными дробями есть Fraction. Обзор всех числовых типов есть в статье про числа в Python.
| Тип | Точность | Скорость | Где использовать |
|---|---|---|---|
float | Около 15-17 цифр, двоичная | Высокая, аппаратная | Наука, графика, измерения, статистика |
Decimal | Задается, десятичная | Ниже | Деньги, налоги, отчеты |
Fraction | Абсолютная | Низкая | Точные дроби, математические задачи |
from decimal import Decimal
from fractions import Fraction
print(Decimal("0.1") + Decimal("0.2")) # 0.3
print(Decimal(0.1)) # 0.1000000000000000055511151231257827...
print(Fraction(1, 3) + Fraction(1, 6)) # 1/2Decimal создают из строки, а не из float: во втором примере видно, что Decimal(0.1) честно сохраняет погрешность исходного float. Подробное описание типа есть в документации Python.
Частые вопросы
Короткие ответы на вопросы, которые часто задают про дробные числа.
Как проверить, что строку можно превратить в float?
Надежнее всего попробовать преобразование в блоке try/except ValueError. Метод str.isdigit() для этого не подходит: он вернет False для строк "-5" и "3.14".
Как убрать .0 у целого результата?
Проверьте x.is_integer() и выведите int(x), либо используйте формат f"{x:g}", который отбрасывает незначащие нули.
Чем int(x) отличается от round(x)?
int() просто отбрасывает дробную часть в сторону нуля: int(2.9) равно 2. round() округляет до ближайшего целого: round(2.9) равно 3.
Почему float("1,5") выдает ошибку?
Функция понимает только точку как разделитель дробной части, независимо от языковых настроек системы. Замените запятую методом replace(",", ".") перед преобразованием.