Методы класса Decimal

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Смотреть материал на YouTube | RuTube

Класс Decimal содержит множество методов для выполнения различных операций над числами. Основные из них следующие:

Метод

Описание

as_integer_ratio()

возвращает кортеж (n, d) для представления числа в виде n/d (числа n, d минимально возможные)

as_tuple()

возвращает представление вещественного числа в виде кортежа (sign, digits, exponent)

normalize()

возвращает нормализованное (стандартное, единообразное) представление числа

copy_abs()

создание копии объекта с модулем числа

copy_negate()

создание копии объекта с противоположным знаком

copy_sign(d)

создание копии объекта со знаком числа d

compare(d)

сравнивает числа self и d, возвращая значения -1 (меньше), 0 (равны), 1 (больше)

Методы проверки принадлежности

is_finite()

возвращает True, если число конечное (ограниченное) и False в противном случае (для 'Infinity' и 'NaN' возвращает False)

is_infinite()

возвращает True для значения 'Infinity' и False для всех остальных

is_nan()

возвращает True для значения 'NaN' и False для всех остальных

is_normal()

возвращает False для 0, 'Infinity', 'NaN' и True для всех остальных

is_signed()

возвращает True для объектов со знаком минус и False для всех остальных

is_zero()

возвращает True для нулевого значения (без учета знака: минус или плюс)

Математические методы

sqrt()

вычисление квадратного корня

exp()

вычисление значения экспоненты

fma(a, b)

вычисление по формуле: self * a + b

ln()

вычисление натурального логарифма

log10()

вычисление десятичного логарифма

max(d)

возвращает наибольшее из двух чисел (self и d)

min(d)

возвращает наименьшее из двух чисел (self и d)

max_mag(d)

возвращает наибольшее из двух чисел (self и d) без учета знака

min_mag(d)

возвращает наименьшее из двух чисел (self и d) без учета знака

shift(p)

возвращает новый объект со смещенными цифрами на p позиций

quantize(ex)

выполняет округление чисел в соответствии с указанной экспонентой ex

Давайте подробнее рассмотрим работу некоторых из них. Пусть в программе имеются следующие объекты:

a = Decimal('5.3')
b = Decimal('-655e-2')
 
d_inf = Decimal('Infinity')
d_nan = Decimal('NaN')

И применим первый метод as_integer_ratio() к объекту a, получим:

a.as_integer_ratio()  # (53, 10)

Возвращается кортеж из двух чисел 53 и 10 – это числитель и знаменатель дроби для представления числа 5.3 = 53/10.

Аналогично для объекта b:

b.as_integer_ratio() # (-131, 20)

Знак минус ставится у первого числа (числителя дроби). При этом числа 131 и 20 – наименьшие (по модулю) из возможных.

Следующий метод as_tuple() мы с вами уже подробно рассматривали на прошлом занятии, поэтому сразу перейдем к методу normalize(). Если его вызвать для объекта b, получим его нормализованное представление:

bn = b.normalize()  # Decimal('-6.55')

Следующий метод:

b_abs = b.copy_abs()  # Decimal('6.55')

создает копию объекта b с модулем числа. Соответственно, метод copy_negate() создает копию объекта с противоположным знаком:

a_ng = a.copy_negate()  # Decimal('-5.3')
a2 = a_ng.copy_negate()  # Decimal('5.3')

И последний из этой серии позволяет задавать знак числа по другому указанному числу. Например:

res = a.copy_sign(b)  # Decimal('-5.3')

Здесь знак «минус» для числа 5.3 был взят из числа b.

Метод compare() сравнивает два числа (объекта) Decimal, возвращая числовые значения -1, 0, 1:

a.compare(b)  # Decimal('1')
a.compare(Decimal('5.3'))  # Decimal('0')
b.compare(a)  # Decimal('-1')

Следующая группа методов проверок числа на различную принадлежность, работают очевидным образом. Например:

a.is_finite()  # True
d_inf.is_finite()  # False
d_nan.is_finite()  # False
d_inf.is_infinite()  # True
d_nan.is_infinite()  # False
b.is_signed()  # True
a.is_signed()  # False

И так далее.

Наибольший интерес, конечно, представляют математические методы. Например:

d = Decimal(9)
res = d.sqrt()  # Decimal('3')

Метод sqrt() возвращает новый объект класса Decimal со значением квадратного корня числа d. По аналогии работают и другие методы:

a.exp()  # Decimal('200.3368099747916848352566156')
a.fma(d, b)  # Decimal('41.15')

Это аналог следующих вычислений:

res = a * d + b  # Decimal('41.15')

Далее:

d.ln()  # Decimal('2.197224577336219382790490474')
a.max(b)  # Decimal('5.3')
a.max_mag(b)  # Decimal('-6.55')
Decimal('3.1415').shift(1)  # Decimal('31.4150')
Decimal('3.1415').shift(-2)  # Decimal('0.0314')

Метод quantize()

Последний метод quantize() позволяет округлять вещественные числа с заданной точностью и разными способами. В самом простом варианте его можно записать в виде:

pi = Decimal('3.1415926535')
pi2 = pi.quantize(Decimal('.00'))  # Decimal('3.14')

Здесь Decimal('.00') задает точность (экспоненту) для округления. Можно прописывать любое вещественное значение и метод quantize() округлит текущее число до указанного знака. Например:

pi.quantize(Decimal('0.12'))  # Decimal('3.14')
pi.quantize(Decimal('0.1234'))  # Decimal('3.1416')
pi.quantize(Decimal('52.1234'))  # Decimal('3.1416')

Целая часть числа здесь не играет никакой роли. Главное, сколько значащих цифр записано после точки.

По аналогии можно округлить и целое число, например:

Decimal('9').quantize(Decimal('.1234'))  # Decimal('9.0000')

Способы округлений чисел класса Decimal

В действительности с числами класса Decimal можно выполнять различные способы округлений. Они следующие:

Режим округления

Описание

ROUND_DOWN

Округление выполняется всегда вниз, независимо от последней цифры, т. е. число всегда уменьшается или остаётся неизменным. Например:

1.5 → 1

1.6 → 1

ROUND_UP

Округление выполняется всегда вверх, увеличивая число или оставляя его неизменным. Например:

1.5 → 2

1.6 → 2

ROUND_HALF_UP

Традиционное округление, известное многим как "школьное": если последняя цифра равна или больше 5, число увеличивается, иначе остается прежним. Например:

1.5 → 2

1.4 → 1

ROUND_HALF_DOWN

Подобен предыдущему, но округление выполняется вниз, если последняя цифра равна 5. Например:

1.5 → 1

1.6 → 2

ROUND_HALF_EVEN

Часто называется банковским округлением. Если последняя цифра равна 5, то округляет число так, чтобы ближайшая целая была чётной. Например:

1.5 → 2 (так как 2 чётное)

2.5 → 2 (также чётное)

ROUND_CEILING

Подобен ROUND_UP, но применяется только к положительным числам. Отрицательные числа округляются в сторону нуля. Например:

1.5 → 2

-1.5 → -1

ROUND_FLOOR

Противоположность ROUND_CEILING. Положительные числа округляются вниз, отрицательные – вверх. Например:

1.5 → 1

-1.5 → -2

ROUND_05UP

Число округляется только тогда, когда последняя цифра равна 0 или 5. В остальных случаях число остается без изменений. Например:

1.05 → 1.1

1.6 → 1.6

Для определения текущего режима округления можно выполнить следующие команды:

import decimal
 
context = decimal.getcontext()
round_mode = context.rounding
print(round_mode)

По умолчанию используется ROUND_HALF_EVEN, т.е. «банковское» округление. Давайте в этом убедимся:

Decimal('7.5').quantize(Decimal('0'))  # Decimal('8')
Decimal('6.5').quantize(Decimal('0'))  # Decimal('6')

Действительно округление выполняется до ближайшего четного числа.

Чтобы поменять режим непосредственно в методе quantize() можно воспользоваться командой:

Decimal('6.5').quantize(Decimal('0'), rounding='ROUND_HALF_UP')

Получим значение 7, т.к. было указано «школьное» округление до ближайшего целого. И так можно задавать любой режим.

Разумеется, округлять можно не только до целого, но до любой желаемой точности, как это мы видели ранее. Здесь ничего не меняется. Например:

Decimal('6.15').quantize(Decimal('0.0'), rounding='ROUND_HALF_UP')

Получим значение 6.2 по «школьному» принципу округления чисел.

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Видео по теме