Основное руководство по типу float в Python с примерами
В этом руководстве вы узнаете о типе данных float в Python, о том, как Python представляет числа с плавающей запятой и как проверить число float на равенство.
Введение в тип float в Python
Python использует класс float для представления действительных чисел.
CPython реализует float, используя тип C double. Тип C double обычно реализует двоичное число с плавающей запятой двойной точности IEEE 754, которое также называется binary64.
Python float использует 8 байтов (или 64 бита) для представления действительных чисел. В отличие от целочисленного типа, тип float использует фиксированное количество байтов.
Технически Python использует 64 бита следующим образом:
- 1 бит для знака (положительного или отрицательного);
- 11 бит для показателя степени 1,5e-5 1,5 x 10-5(показатель степени -5), диапазон: [-1022, 1023];
- 52 бита для значащих цифр.
Для простоты значащими цифрами являются все цифры, кроме ведущих и конечных нулей.
Например, 0,25 имеет две значащие цифры, 0,125 — три значащие цифры, а 12,25 — четыре значащие цифры.
(1,25)10 =(1×20 + 0x2-1 + 1×2-2)10 =(1,01)2
Некоторые числа имеют конечное двоичное представление, а некоторые нет, например 0,1. Это 01.0001100110011… в двоичном формате.
Из-за этого Python может использовать для этих чисел только приблизительные представления с плавающей запятой.
Класс float в Python
float() возвращает число с плавающей запятой на основе числа или строки. Например:
>>> float(0.1) 0.1 >>> float('1.25') 1.25
Если вы передадите объект(obj) в метод float(obj), он будет делегирован в obj.__float__(). Если __float__() не определен, он вернется к __index__().
Если вы не передадите ни одного аргумента в функцию float(), она вернет 0,0. Когда вы используете функцию print(), вы увидите, что число 0,1 представлено точно как 0,1. Внутри Python может представлять только приблизительно 0,1.
Чтобы увидеть, как Python представляет 0.1 внутри, вы можете использовать функцию format().
Ниже показано, как Python представляет число 0,1 с помощью 20 цифр:
>>> format(0.1, '.20f') '0.10000000000000000555'
Как видите, 0,1 — это не совсем 0,1, а 0,10000000000000000555…
Поскольку Python может приблизительно представлять некоторые числа с плавающей запятой, это вызовет множество проблем при сравнении двух чисел с плавающей запятой.
Проверка равенства
Давайте посмотрим на следующий пример:
x = 0.1 + 0.1 + 0.1 y = 0.3 print(x == y)
Выход:
False
Внутри Python не может использовать конечное число цифр для представления чисел x и y:
print(format(x, '.20f')) print(format(y, '.20f'))
Выход:
0.30000000000000004441 0.29999999999999998890
Обратите внимание, что количество цифр бесконечно. Мы показываем только первые 20 цифр.
Один из способов обойти эту проблему — округлить обе части выражения равенства до числа значащих цифр. Например:
x = 0.1 + 0.1 + 0.1 y = 0.3 print(round(x, 3) == round(y, 3))
Выход:
True
Этот обходной путь работает не во всех случаях.
PEP485 предлагает решение, устраняющее эту проблему, используя относительные и абсолютные допуски.
Он предоставляет функцию isclose() из математического модуля, возвращающую True, если два числа относительно близки друг к другу.
Ниже показана сигнатура функции isclose():
isclose(a, b, rel_tol=1e-9, abs_tol=0.0)
Например:
from math import isclose x = 0.1 + 0.1 + 0.1 y = 0.3 print(isclose(x,y))
Выход:
True