Числа в Python — CodeChick
В этой статье вы узнаете, какие типы чисел есть в Python, научитесь приводить один тип к другому и производить с числами математические операции.
Какие числа поддерживаются
Python поддерживает комплексные (complex), целые числа (integer) и числа с плавающей точкой (float).
Целые числа и числа с плавающей точкой отличаются наличием или отсутствием десятичного разделителя. Например, 5
— целое число, а 5.0
— число с плавающей точкой.
Целые числа могут быть любой длины. Точность чисел с плавающей точкой обеспечивается только до 15 знака, на 16 могут возникать неточности.
Комплексные числа записываются следующим образом: x + yj
. Здесь x
— действительная часть, а y
— мнимая.
Чтобы узнать, к какому типу относится переменная, используйте функцию type()
. Если вы хотите узнать, принадлежит ли переменная определенному классу, используйте isinstance()
.
a = 5 print(type(a)) print(type(5.0)) c = 5 + 3j print(c + 3) print(isinstance(c, complex))
Вывод:
<class 'int'>
<class 'float'>
(8+3j)
True
Системы счисления
Числа, с которыми мы ежедневно сталкиваемся, представлены в десятичной системе счисления. Но программисты чащего всего работают с двоичной (основанием 2), шестнадцатеричной (основание 16) и восьмеричной (основание 8) системами счисления.
Эти числа в Python могут быть представлены с помощью соответствующего префикса. Они записаны в таблице ниже.
Система счисления | Префикс |
Двоичная |
'0B' |
Восьмеричная |
|
Шестнадцатеричная |
|
Вот как это выглядит:
# выведет 107 print(0b1101011) # выведет 253, т. к. 251 + 2) = 253 print(0xFB + 0b10) # выведет 13 print(0o15)
Вывод:
107
253
13
Приведение типов
В Python один тип числа можно конвертировать в другой. Это называется приведением типов.
Операции вроде сложения или вычитания неявно, то есть автоматически, приводят целочисленный тип к числу с плавающей точкой, если один из операндов является числом с плавающей точкой.
>>> 1 + 2.0 3.0
Как видите, при сложении 1 (это целое число) приводится к 1.0 (это число с плавающей точкой). Результат тоже будет числом с плавающей точкой.
Чтобы выполнить явное преобразование, вы можете использовать встроенные функции int()
, float()
, complex()
. С помощью них к численным типам можно приводить даже строки.
>>> int(2.3) 2 >>> int(-2.8) -2 >>> float(5) 5.0 >>> complex('3+5j') (3+5j)
При приведении числа с плавающей точкой к целому десятичная часть удаляется. Говорят, что она «обрезается».
Модуль decimal
Встроенный класс float порой может выдавать удивительные результаты. Все мы знаем, что 1.1 + 2.2 = 3.3, но Python, кажется, так не думает.
Введите в IDLE на своем компьютере такую строку:
>>> (1.1 + 2.2) == 3.3 False
Почему False
? Что не так?
Приведем пример. Мы не можем представить дробь ⅓ в виде десятичного числа. ⅓ = 0.33333333… период — бесконечный. Поэтому хранить можно лишь приблизительное значение этого числа.
То есть десятичная дробь 0.1 — это бесконечная двоичная дробь 0.000110011001100110011… и компьютер может хранить в памяти только конечное число цифр после точки. Это лишь приближенное к 0.
>>> 1.1 + 2.2 3.3000000000000003
Для решения этой проблемы мы можем использовать модуль decimal, встроенный в Python. Тип float имеет точность до 15 знаков, а decimal — настраиваемую пользователем.
Разница налицо:
import decimal print(0.1) print(decimal.Decimal(0.1))
Вывод:
0.1
0.1000000000000000055511151231257827021181583404541015625
Этот модуль полезен, когда нам нужно вычислять десятичные дроби так же, как в школе.
Положение точки тоже сохраняется. Мы знаем, что 25.50 кг точнее, чем 25.5 кг, так как у этой дроби два числа после точки.
from decimal import Decimal as D print(D('1.1') + D('2.2')) print(D('1.2') * D('2.50'))
Вывод:
3.3
3.000
Обратите внимание на нули в вышеприведенном примере.
Вы можете подумать: почему бы тогда не использовать модуль decimal вместо float постоянно? Справедливый вопрос.
Дело в эффективности. Операции с float происходят гораздо быстрее, чем с decimal.
Когда стоит использовать decimal вместо float?
- При создании приложения для работы с финансами. Здесь нужна точность.
- Когда нужно держать уровень точности на определенном уровне.
- Когда нужно реализовать дробь с определенным числом цифр после точки.
Модуль fractions
В Python есть модуль fractions, он производить операции с дробными числами.
У дробей есть числитель и знаменатель — это целые числа. Также этот модуль позволяет производить операции с рациональными числами.
Создать fraction-объект можно разными способами. Давайте их разберем:
import fractions print(fractions.Fraction(1.5)) print(fractions.Fraction(5)) print(fractions.Fraction(1,3))
Вывод:
3/2
5
1/3
При создании fraction-объекта из float могут возникнуть неожиданные результаты. Происходит это, как говорилось выше, из-за несовершенного двоичного представления чисел с плавающей точкой.
К счастью, fraction позволяет создать экземпляр из строки. Настоятельно рекомендуем использовать именно этот способ, когда аргументом является десятичное число.
import fractions # Число с плавающей точкой # Вывод: 2476979795053773/2251799813685248 print(fractions.Fraction(1.1)) # Строка # Вывод: 11/10 print(fractions.Fraction('1.1'))
Вывод:
2476979795053773/2251799813685248
11/10
Этот тип данных поддерживает все базовые математические операции.
from fractions import Fraction as F # со всеми работает print(F(1, 3) + F(1, 3)) print(1 / F(5, 6)) print(F(-3, 10) > 0) print(F(-3, 10) < 0)
Вывод:
2/3
6/5
False
True
Модуль math и random
Для решения тригонометрических, логарифмических, вероятностных и статистических задач Python располагает встроенными модулями math и random.
import math print(math.pi) print(math.cos(math.pi)) print(math.exp(10)) print(math.log10(1000)) print(math.sinh(1)) print(math.factorial(6))
Вывод:
3.141592653589793
-1.0
22026.465794806718
3.0
1.1752011936438014
720
👉Полный список функций и атрибутов модуля math.
import random print(random.randrange(10, 20)) x = ['а', 'б', 'в', 'г', 'д'] # Получаем случайный набор из х print(random.choice(x)) # Перемешиваем x random.shuffle(x) # Выводим в консоль перемешанный список x print(x) # Выводим в консоль случайный элемент print(random.random())
Примечание. Ваш вывод может отличать, поскольку функции модуля random выбирают элементы случайно.
Вывод:
13
а
['г', 'б', 'д', 'а', 'в']
0. 038881285348306704
👉Полный список функция и атрибутов модуля random.
3 особенности чисел в Python, о которых вы, возможно, не знали / Хабр
Если вы писали код на Python, то весьма высока вероятность того, что вы, хотя бы в одной из своих программ, пользовались числами. Например, это могли быть целые числа для указания индекса значения в списке, или числа с плавающей точкой, представляющие суммы в некоей валюте.
Но числа в Python — это гораздо больше, чем, собственно, их числовые значения. Поговорим о трёх особенностях чисел в Python, с которыми вы, возможно, не знакомы.
№1: у чисел есть методы
В Python практически всё — это объект. Один из первых объектов, о котором узнаёт тот, кто начинает изучать Python — это str
, используемый для представления строк. Возможно, вы сталкивались с использованием методов строк, вроде
, который возвращает новую строку, все символы которой приведены к нижнему регистру:
>>> "HELLO". lower() 'hello'
Числа в Python тоже, как и строки, являются объектами. У них тоже есть методы. Например, целое число можно преобразовать в байтовую строку с помощью метода .to_bytes()
:
>>> n = 255 >>> n.to_bytes(length=2, byteorder="big") b'\x00\xff'
Параметр length
указывает на количество байт, которые нужно использовать при составлении байтовой строки, а параметр byteorder
определяет порядок байт. Например, установка параметра byteorder
в значение «big»
приводит к возврату байтовой строки, в которой старший байт расположен первым, а установка этого параметра в значение «little»
приводит к тому, что первым идёт младший байт.
255 — это максимальное значение, которое может принимать 8-битное целое число. Поэтому в нашем случае при вызове метода .to_bytes()
можно без проблем воспользоваться параметром length=1
:
>>> n.to_bytes(length=1, byteorder="big") b'\xff'
А вот если записать в n
число 256 и вызвать для него . to_bytes()
с параметром length=1
, будет выдана ошибка OverflowError
:
>>> n = 256 >>> n.to_bytes(length=1, byteorder="big") Traceback (most recent call last): File "<stdin>", line 1, in <module> OverflowError: int too big to convert
Преобразовать байтовую строку в целое число можно, воспользовавшись методом .from_bytes()
класса int
:
>>> int.from_bytes(b'\x06\xc1', byteorder="big") 1729
Методы класса вызывают, используя имя класса, а не его экземпляр. Именно поэтому в предыдущем примере метод .from_bytes()
вызывают, обращаясь к int
.
Любопытный факт: 1729 — это самое маленькое положительное число, которое можно представить в виде суммы кубов двух положительных чисел двумя способами. Исторический анекдот связывает это число с индийским математиком Сринивасой Рамануджаном, который рассказал о нём своему наставнику Готфри Харолду Харди.
Харди часто навещал Рамануджана, когда тот, умирая, находился в больнице в Патни. Именно в одно из таких посещений произошёл «инцидент» с номером такси. Харди приехал в Патни на такси, воспользовавшись своим излюбленным транспортным средством. Он вошёл в палату, где лежал Рамануджан. Начинать разговор Харди всегда было мучительно трудно, и он произнёс свою первую фразу: «Если не ошибаюсь, то номер такси, на котором я приехал, 1729. Мне кажется, это скучное число». На что Рамануджан тотчас же ответил: «Нет, Харди! О нет! Это очень интересное число. Это самое малое из чисел, представимых в виде суммы двух кубов двумя различными способами».
Один из способов представления числа 1729 в виде суммы двух кубов — это 13 + 123. Можете отыскать второй способ?
У чисел с плавающей точкой тоже есть методы. Возможно, самый полезный из них — это .is_integer()
. Его используют для проверки того, есть ли у числа с плавающей точкой дробная часть:
>>> n = 2. 0 >>> n.is_integer() True >>> n = 3.14 >>> n.is_integer() False
Вот — интересный метод .as_integer_ratio()
. Он, вызванный для числа с плавающей точкой, возвращает кортеж, содержащий числитель и знаменатель дроби, представляющей это число:
>>> n.as_integer_ratio() (1, 2)
Правда, из-за ошибки представления чисел с плавающей точкой, иногда этот метод возвращает неожиданные результаты:
>>> n = 0.1 >>> n.as_integer_ratio() (3602879701896397, 36028797018963968)
Если надо — можно вызывать методы на числовых литералах, заключённых в круглые скобки:
>>> (255).to_bytes(length=1, byteorder="big") b'\xff' >>> (3.14).is_integer() False
Если обойтись без скобок — при попытке вызова метода на целочисленном литерале будет выдана ошибка SyntaxError
. А вот при вызове метода числового литерала с плавающей точкой отсутствие скобок, что странно, не приведёт к ошибке:
>>> 255. SyntaxError: invalid syntax >>> 3.14.is_integer() False
Полный список методов числовых Python-типов можно найти в документации.
№2: числа обладают иерархией
В математике числа обладают естественной иерархией. Например, все натуральные числа являются целыми, а все целые числа — рациональными. Все рациональные числа — это вещественные числа, а все вещественные числа — это комплексные числа.
Похожие рассуждения применимы и к представлению чисел в Python. Здесь «числовая башня» выражается через абстрактные типы, содержащиеся в модуле numbers
.
Числовая башня
Все числа в Python являются экземплярами класса Number
:
>>> from numbers import Number >>> # Целые числа являются наследниками Number >>> isinstance(1729, Number) True >>> # Числа с плавающей точкой являются наследниками Number >>> isinstance(3.14, Number) True >>> # Комплексные числа являются наследниками Number >>> isinstance(1j, Number) True
Если нужно узнать о том, является ли некое Python-значение числовым, но при этом неважно то, каким именно числовым типом оно представлено, воспользуйтесь конструкцией isinstance(value, Number)
.
В Python имеется четыре дополнительных абстрактных типа, иерархия которых, начиная с наиболее общего числового типа, выглядит так:
Класс
Complex
используется для представления комплексных чисел. Тут имеется один встроенный конкретный тип —complex
.Класс
Real
— это представление вещественных чисел. Его единственный встроенный конкретный тип —float
.Класс
Rational
представляет рациональные числа. Его единственным встроенным конкретным типом являетсяFraction
.Класс
Integral
применяют для представления целых чисел. В нём имеется два встроенных конкретных типа —int
иbool
.
Так, погодите, а значения типа bool
— это разве числа? Да — числа. Можете это проверить, воспользовавшись REPL:
>>> import numbers >>> # Комплексные числа являются наследниками Complex >>> isinstance(1j, numbers. Complex) True >>> # Комплексные числа не являются наследниками Real >>> isinstance(1j, numbers.Real) False >>> # Числа с плавающей точкой являются наследниками Real >>> isinstance(3.14, numbers.Real) True >>> # Числа с плавающей точкой не являются наследниками Rational >>> isinstance(3.14, numbers.Rational) False >>> # Объекты Fractions - это не наследники Rational >>> from fractions import Fraction >>> isinstance(Fraction(1, 2), numbers.Rational) True >>> # Объекты Fractions - это не наследники Integral >>> isinstance(Fraction(1, 2), numbers.Integral) False >>> # Целые числа - это наследники Integral >>> isinstance(1729, numbers.Integral) True >>> # Логические значения - это наследники Integral >>> isinstance(True, numbers.Integral) True >>> True == 1 True >>> False == 0 True
Всё это, на первый взгляд, выглядит вполне нормально. Правда, порядок несколько нарушает то, что значения типа bool
являются числами.
Странность Python: так как тип bool
относится к классу Integral
(на самом деле он — прямой наследник int
), со значениями True
и False
можно вытворять довольно необычные вещи.
Например, True
можно использовать в роли индекса для того чтобы получить второй элемент итерируемого объекта. А если поделить число на False
— будет выдана ошибка ZeroDivisionError
.
Попробуйте выполнить «False»[True]
и 1 / False
в REPL!
Но если присмотреться к числовым типам поближе, окажется, что в иерархии Python-чисел имеется пара своеобразных моментов.
Числа типа Decimal не укладываются в иерархию
Как уже было сказано, в «числовой башне» Python есть 4 конкретных числовых типа, соответствующих четырём абстрактным типам: complex
, float
, Fraction
и int
. Но в Python имеется и пятый числовой тип, представленный классом Decimal
. Этот тип используется для точного представления десятичных чисел и для преодоления ограничений арифметических операций с плавающей точкой.
Можно предположить, что числа типа Decimal
являются наследниками Real
, но это, на самом деле, не так:
>>> from decimal import Decimal >>> import numbers >>> isinstance(Decimal("3.14159"), numbers.Real) False
Единственный класс, наследником которого является класс Decimal
— это Number
:
>>> isinstance(Decimal("3.14159"), numbers.Complex) False >>> isinstance(Decimal("3.14159"), numbers.Rational) False >>> isinstance(Decimal("3.14159"), numbers.Integral) False >>> isinstance(Decimal("3.14159"), numbers.Number) True
Логично то, что класс Decimal
не является наследником Integral
. В некоторой степени смысл есть и в том, что Decimal
не является наследником Rational
. Но почему Decimal
не является наследником Real
или Complex
?
Ответ кроется в исходном коде CPython:
Объекты Decimal обладают всеми методами, определёнными в классе Real, но эти объекты не должны регистрироваться в виде наследников Real, так как Decimal-числа не взаимодействуют с двоичными числами с плавающей точкой (например, результат операции Decimal(‘3.14’) + 2.71828 не определён). Но ожидается, что числа, классы которых являются наследниками абстрактного класса Real, способны взаимодействовать друг с другом (то есть — R1+R2 должно вычисляться в том случае, если числа R1 и R2 представлены типами, являющимися наследниками Real).
Получается, что объяснение странностей сводится к особенностям реализации.
Числа с плавающей точкой — странные создания
А вот числа с плавающей точкой, с другой стороны, реализуют абстрактный базовый класс Real
. Они используются для представления вещественных чисел. Но, из-за того, что компьютерная память не является неограниченным ресурсом, числа с плавающей точкой — это лишь конечные аппроксимации вещественных чисел. Это приводит к возможности написания «ненормальных» образцов кода вроде такого:
>>> 0.1 + 0.1 + 0.1 == 0.3 False
Числа с плавающей точкой хранятся в памяти в виде двоичных дробей. Это приводит к появлению некоторых проблем. Например, у дроби 1/3 нет конечного десятичного представления (после десятичной точки идёт бесконечное множество троек). А у дроби 1/10 нет конечного представления в виде двоичной дроби.
Другими словами, в компьютере нельзя совершенно точно представить число 0,1 — если только этот компьютер не обладает бесконечной памятью.
Со строго математической точки зрения все числа с плавающей точкой — это рациональные числа, за исключением float(«inf»)
и float(«nan»)
. Но программисты используют их в роли аппроксимаций вещественных чисел и воспринимают их, по большей части, как вещественные числа.
Странность Python: float(«nan»)
— это особое значение с плавающей точкой, представляющее собой «не число». Такие значения часто обозначают как NaN
. Но, так как float
— это числовой тип, isinstance(float(«nan»), Number)
возвращает True
.
Получается, что «не числа» — это числа.
В общем, числа с плавающей точкой — странные создания.
№3: набор числовых типов Python можно расширять
Абстрактный числовой базовый тип Python позволяет программисту создавать собственные абстрактные и конкретные числовые типы.
В качестве примера рассмотрим класс ExtendedInteger
, который реализует числа в форме a+b√p, где a
и b
— целые числа, а p
— простое число (обратите внимание: класс не обеспечивает то, что число p
является простым):
import math import numbers class ExtendedInteger(numbers.Real): def init(self, a, b, p = 2) -> None: self. a = a self.b = b self.p = p self._val = a + (b * math.sqrt(p)) def repr(self): return f"{self.class.name}({self.a}, {self.b}, {self.p})" def str(self): return f"{self.a} + {self.b}√{self.p}" def trunc(self): return int(self._val) def float(self): return float(self._val) def hash(self): return hash(float(self._val)) def floor(self): return math.floor(self._val) def ceil(self): return math.ceil(self._val) def round(self, ndigits=None): return round(self._val, ndigits=ndigits) def abs(self): return abs(self._val) def floordiv(self, other): return self._val // other def rfloordiv(self, other): return other // self._val def truediv(self, other): return self._val / other def rtruediv(self, other): return other / self._val def mod(self, other): return self. _val % other def rmod(self, other): return other % self._val def lt(self, other): return self._val < other def le(self, other): return self._val <= other def eq(self, other): return float(self) == float(other) def neg(self): return ExtendedInteger(-self.a, -self.b, self.p) def pos(self): return ExtendedInteger(+self.a, +self.b, self.p) def add(self, other): if isinstance(other, ExtendedInteger): # Если оба экземпляра имеют одно и то же значение p, # вернуть новый экземпляр ExtendedInteger if self.p == other.p: new_a = self.a + other.a new_b = self.b + other.b return ExtendedInteger(new_a, new_b, self.p) # В противном случае вернуть значение типа float else: return self._val + other._val # Если other - значение класса Integral, прибавить значение other к значению self. a elif isinstance(other, numbers.Integral): new_a = self.a + other return ExtendedInteger(new_a, self.b, self.p) # Если other - значение класса Real, вернуть значение типа float elif isinstance(other, numbers.Real): return self._val + other._val # Если тип other неизвестен, позволить другим принять решение # о том, что делать в такой ситуации else: return NotImplemented def radd(self, other): # Сложение коммутативно, поэтому прибегнуть к add return self.add(other) def mul(self, other): if isinstance(other, ExtendedInteger): # Если оба экземпляра имеют одно и то же значение p, # вернуть новый экземпляр ExtendedInteger if self.p == other.p: new_a = (self.a * other.a) + (self.b * other.b * self.p) new_b = (self.a * other.b) + (self.b * other.a) return ExtendedInteger(new_a, new_b, self. p) # в противном случае вернуть значение типа float else: return self._val * other._val # Если other - значение класса Integral, умножить его компоненты a и b на other elif isinstance(other, numbers.Integral): new_a = self.a * other new_b = self.b * other return ExtendedInteger(new_a, new_b, self.p) # Если other - значение класса Real, вернуть значение типа float elif isinstance(other, numbers.Real): return self._val * other # Если тип other неизвестен, позволить другим принять решение # о том, что делать в такой ситуации else: return NotImplemented def rmul(self, other): # Умножение коммутативно, поэтому прибегнуть к mul return self.mul(other) def pow(self, exponent): return self._val ** exponent def rpow(self, base): return base ** self._val
Для того чтобы обеспечить правильность реализации интерфейса Real
конкретным типом — нужно создать реализации множества методов, в именах которых есть два символа подчёркивания. Ещё нужно поразмыслить о том, как методы вроде .add()
и .mul()
взаимодействуют с другими типами, являющимися наследниками Real
.
Обратите внимание: вышеприведённый пример не создавался в расчёте на его полноту или абсолютную правильность. Его цель — продемонстрировать читателю возможности работы с числами.
При наличии реализации ExtendedInteger
можно заниматься следующими вычислениями:
>>> a = ExtendedInteger(1, 2) >>> b = ExtendedInteger(2, 3) >>> a ExtendedInteger(1, 2, 2) >>> # Проверяем то, что a - это наследник Number >>> isinstance(a, numbers.Number) True >>> # Проверяем то, что a - это наследник Real >>> isinstance(a, numbers.Real) True >>> print(a) 1 + 2√2 >>> a * b ExtendedInteger(14, 7, 2) >>> print(a * b) 14 + 7√2 >>> float(a) 3.8284271247461903
Иерархия числовых типов в Python — довольно гибкая структура. Но, конечно, всегда стоит очень внимательно относиться к реализации типов, являющихся наследниками встроенных абстрактных базовых типов Python. Нужно обеспечить их корректную работу друг с другом.
В документации по Python можно найти несколько советов по реализации собственных типов, которые стоит прочесть тому, кто решит заняться созданием собственных числовых типов. Такому человеку ещё полезно будет ознакомиться с реализацией Fraction
.
Итоги
Вот — те три особенности Python-чисел, которые мы здесь обсуждали:
У чисел есть методы, как и у практически всех остальных объектов в Python.
Числа обладают иерархией, даже несмотря на то, что их чёткие взаимоотношения несколько портит наличие типов
Decimal
иfloat
.Программисты могут создавать собственные числовые типы, которые вписываются в иерархию числовых типов Python.
Может быть, вы узнали из этого материала не только об этих особенностях чисел, но и ещё о чём-нибудь, что вам пригодится.
О, а приходите к нам работать? 😏Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.
Мы предлагаем интересные и сложные задачи по анализу данных и low latency разработке для увлеченных исследователей и программистов. Гибкий график и никакой бюрократии, решения быстро принимаются и воплощаются в жизнь.
Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.
Присоединяйтесь к нашей команде.
чисел — Числовые абстрактные базовые классы — Документация по Python 3.11.3
Исходный код: Lib/numbers.py
Модуль номеров
( PEP 3141 ) определяет иерархию числовых
абстрактные базовые классы, которые постепенно определяют
больше операций. Ни один из типов, определенных в этом модуле, не предназначен для создания экземпляров.
- класс номеров.Номер
Корень числовой иерархии. Если вы просто хотите проверить, является ли аргумент x — это число, неважно, какого рода, используйте
isinstance(x, Number)
.
Числовая башня
- класс номеров.Комплекс
Подклассы этого типа описывают комплексные числа и включают операции которые работают на встроенном комплексе
типа
. Это: преобразования всложный
илогический
,реальный
,образ
,+
,-
,*
,/
,**
,абс()
,сопряженное()
,==
, и!=
. Все, кроме-
и!=
, являются абстрактными.- настоящий
Реферат. Извлекает действительную составляющую этого числа.
- изображение
Реферат. Извлекает мнимую составляющую этого числа.
- абстрактный метод сопряженный ()
Реферат. Возвращает комплексное сопряжение. Например,
(1+3j).conjugate() == (1-3j)
.
- класс номеров.Настоящий
К
Complex
,Real
добавляет операции, которые работают с реальными числа.Короче говоря, это: преобразование в
float
,math.trunc()
,round()
,math.floor()
,math.ceil()
,divmod()
,//
,%
,<
,<=
,>
и>=
.Real также предоставляет значения по умолчанию для
complex()
,real
,imag
иconjugate()
.
- класс номеров.Rational
Подтипы
Действительное
и добавляетчислитель
изнаменатель
свойств. Он также обеспечивает значение по умолчанию дляс плавающей запятой()
.Числитель
знаменатель
значений должны быть экземплярамиIntegral
и должны быть в наименьших условиях сзнаменатель
положительный.- числитель
Реферат.
- знаменатель
Реферат.
- класс номеров. Интеграл
Subtypes
Rational
и добавляет преобразование в 9,|
,~
.
Примечания для разработчиков типа
Разработчики должны быть осторожны, чтобы сделать равные числа равными и хешировать
их к одним и тем же значениям. Это может быть тонко, если есть два разных
расширения действительных чисел. Например, дроби . Дробь
реализует hash()
следующим образом:
по определению __hash__(я): если self. знаменатель == 1: # Получить целые числа правильно. хэш возврата (self.numerator) # Дорогая проверка, но точно правильная. если я == поплавок (я): вернуть хэш (с плавающей запятой (сам)) еще: # Используйте хэш кортежа, чтобы избежать высокой частоты коллизий на # простые дроби. хеш возврата((self.numerator, self.denominator))
Добавление дополнительных числовых ABC
Есть, конечно, и другие возможные азбуки для чисел, и это было бы
быть плохой иерархией, если она исключает возможность добавления
те. Вы можете добавить MyFoo
между Complex
и Реальный
с:
класс MyFoo (комплекс): ... MyFoo.register(Настоящий)
Реализация арифметических операций
Мы хотим реализовать арифметические операции так, чтобы смешанный режим
операции либо вызывают реализацию, автор которой знал о
типы обоих аргументов или преобразовать оба в ближайший встроенный тип
и сделать операцию там. Для подтипов Интеграл
, это
означает, что __add__()
и __radd__()
должны быть определены как:
класс MyIntegral(Integral): def __add__(я, другой): если isinstance (другое, MyIntegral): вернуть do_my_adding_stuff(я, другой) elif isinstance (другое, OtherTypeIKnowAbout): вернуть do_my_other_adding_stuff(я, другой) еще: вернуть нереализованный def __radd__(я, другой): если isinstance (другое, MyIntegral): вернуть do_my_adding_stuff(другое, себя) elif isinstance (другое, OtherTypeIKnowAbout): вернуть do_my_other_adding_stuff(другое, себя) elif isinstance (другой, интеграл): вернуть int(другое) + int(себя) elif isinstance (другое, реальное): вернуть поплавок (другой) + поплавок (сам) elif isinstance (другой, сложный): вернуть комплекс (другой) + комплекс (я) еще: вернуть нереализованный
Существует 5 различных случаев для операции смешанного типа над подклассами Комплекс
. Я буду ссылаться на весь приведенный выше код, который не
см. MyIntegral
и OtherTypeIKnowAbout
как
«шаблон». a
будет экземпляром A
, который является подтипом
Комплекс
( a : A <: Комплекс
) и b : B <:
Комплекс
. Я рассмотрю a + b
:
Если
А
определяет__add__()
который принимаетb
, все хорошо.Если
A
возвращается к стандартному коду, вернуть значение из__add__()
, мы бы упустили возможность чтоB
определяет более интеллектуальный__radd__()
, поэтому шаблон должен возвращатьNotImplemented
из__добавить__()
. (Илиможет не реализовать
__add__()
в все.)Затем
B
__radd__()
получает шанс. Если он принимаети
, все хорошо.Если он возвращается к шаблону, больше нет возможных методы, чтобы попробовать, так что это где реализация по умолчанию должен жить.
Если
B <: A
, Python пытается использоватьB.__radd__
доА.__добавить__
. Это нормально, потому что это было реализовано с помощью знаниеA
, поэтому он может обрабатывать эти экземпляры до делегированиеКомплекс
.
Если A <: Сложные
и B <: Действительное
без обмена какими-либо другими знаниями,
тогда подходящей общей операцией является операция, включающая встроенный
в комплексе
, и оба __radd__()
приземляются там, поэтому a+b
== б+а
.
Поскольку большинство операций над любым данным типом будут очень похожими,
может быть полезно определить вспомогательную функцию, которая генерирует
прямые и обратные экземпляры любого заданного оператора. Например, дробей.Дробь
использует:
по определению _operator_fallbacks (мономорфный_оператор, резервный_оператор): защита вперед (а, б): если isinstance(b, (int, Fraction)): вернуть monomorphic_operator(a, b) elif isinstance(b, float): вернуть fallback_operator (с плавающей запятой (а), б) elif isinstance (b, комплекс): вернуть fallback_operator (комплекс (а), б) еще: вернуть нереализованный forward.__name__ = '__' + fallback_operator.__name__ + '__' вперед.__doc__ = мономорфный_оператор.__doc__ деф реверс(б, а): если isinstance(a, Rational): # Включает целые числа. вернуть monomorphic_operator(a, b) elif isinstance(a, Real): return fallback_operator (с плавающей запятой (a), с плавающей запятой (b)) elif isinstance(a, Комплекс): return fallback_operator (комплекс (а), комплекс (б)) еще: вернуть нереализованный reverse. __name__ = '__r' + резервный_оператор.__name__ + '__' reverse.__doc__ = monomorphic_operator.__doc__ возврат вперед, назад определение _add (а, б): """а + б""" return Fraction (a.числитель * b.знаменатель + б.числитель * а.знаменатель, а.знаменатель * б.знаменатель) __add__, __radd__ = _operator_fallbacks(_add, operator.add) # ...
Числа Python, преобразование типов и математика (с примерами)
В этом руководстве вы узнаете о числах Python, преобразовании типов и математике с помощью примеров.
Числовые типы данных используются для хранения числовых значений.
Python поддерживает целые числа, числа с плавающей запятой и комплексные числа. В Python они определены как классы int
, float
и complex
.
-
ряд
- содержит целые числа со знаком неограниченной длины. -
float
- содержит числа с плавающей запятой и точность до 15 знаков после запятой. -
комплекс
- содержит комплексные числа.
Числовой тип данных Python
Целые числа и числа с плавающей запятой разделяются наличием или отсутствием десятичной точки. Например,
- 5 — это целое число .
- 5.42 — число с плавающей запятой.
Комплексные числа записываются в виде x + yj
, где x
— действительная часть, а y
— мнимая часть.
Мы можем использовать функцию type()
, чтобы узнать, к какому классу принадлежит переменная или значение.
Давайте посмотрим пример,
num1 = 5 print(num1, 'имеет тип', type(num1)) число2 = 5,42 печать (число2, 'имеет тип', тип (число2)) число3 = 8+2j print(num3, 'имеет тип', type(num3))
Вывод
5 имеет тип <класс 'int'> 5.42 имеет тип(8+2j) имеет тип
В приведенном выше примере мы создали три переменные с именами num1 , num2 и num3 со значениями 5 , 5,42 , 900 8+2j
соответственно.
Мы также использовали функцию type()
, чтобы узнать, к какому классу принадлежит определенная переменная. С
- 5 является целым числом,
type()
возвращаетint
как класс num1 т.е. - 5.42 - это значение с плавающей запятой,
type()
возвращает float как класс num2 , т.е. -
1 + 2j
— комплексное число,type()
возвращает комплекс как класс num3 , т. е.
Системы счисления
Числа, с которыми мы имеем дело каждый день, имеют десятичную систему счисления (основание 10) .
Но программисты должны работать с двоичной (основание 2) , шестнадцатеричной (основание 16) и восьмеричной (основание 8) системами счисления.
В Python мы можем представить эти числа, поместив соответствующий префикс перед этим числом. В следующей таблице перечислены эти префиксы.
Система счисления | Префикс |
---|---|
Двоичный | 0b или 0B |
Восьмеричный | 00 или 00 |
Шестнадцатеричный | 0x или 0X |
Вот несколько примеров
print(0b1101011) # отпечатков 107 print(0xFB + 0b10) # печатает 253 print(0o15) # печатает 13
Преобразование типов в Python
В программировании преобразование типов — это процесс преобразования одного типа числа в другой.
Такие операции, как сложение и вычитание, неявно (автоматически) преобразуют целые числа в числа с плавающей точкой, если один из операндов является числом с плавающей запятой. Например,
print(1 + 2. 0) # выводит 3.0
Здесь мы видим выше, что 1 (целое) преобразуется в 1.0 (с плавающей запятой) для сложения, и результат также является числом с плавающей запятой.
Явное преобразование типов
Мы также можем использовать встроенные функции, такие как int()
, float()
и complex()
для явного преобразования между типами. Эти функции могут даже конвертировать из строк.
число1 = целое (2.3) print(num1) # печатает 2 число2 = целое (-2,8) print(num2) # печатает -2 число3 = число с плавающей запятой (5) print(num3) # печатает 5.0 число4 = комплекс('3+5j') print(num4) # печатает (3 + 5j)
Здесь при преобразовании из числа с плавающей запятой в целое число усекается (удаляются десятичные части).
Аналогичным образом при преобразовании из целого числа в число с плавающей запятой .0
добавляется к числу в постфиксе.
Случайный модуль Python
Python предлагает модуль random
для генерации случайных чисел или выбора случайного элемента из итератора.
Сначала нам нужно импортировать модуль random
. Например,
случайный импорт печать (случайный. случайный диапазон (10, 20)) список1 = ['а', 'б', 'с', 'г', 'е'] # получить случайный элемент из list1 печать (случайный выбор (список1)) # Перемешать список1 случайный. случайный (список1) # Распечатать перетасованный список1 печать (список1) # Напечатать случайный элемент печать(случайный.случайный())
Выход
15 а ['д', 'б', 'в', 'е', 'а'] 0,6716121217631744
Чтобы узнать больше о модуле random
, посетите Python Random Module.
Python Mathematics
Python предлагает модуль math
для выполнения различных математических операций, таких как тригонометрия, логарифмы, вероятность и статистика и т. д. Например,
import math печать (math.pi) печать (math.cos (math.pi)) печать (математика.выражение (10)) печать (математика. log10 (1000)) печать (математика.