Что такое decimal python
Десятичный модуль(Decimal) Python
В этой статье мы рассмотрим один из интересных модулей — модуль Python Decimal.
Мы часто сталкиваемся с необходимостью поиска функций для выполнения математических операций. Десятичный модуль в Python предоставляет нам все необходимые математические функции.
Что такое десятичный модуль в Python?
Десятичный модуль Python содержит различные функции для обработки числовых данных и выполнения с ними различных математических операций. Используя модуль decimal, мы можем эффективно обрабатывать десятичные числа в программе.
The decimal module предоставляет нам функции для управления и преодоления проблемы точности десятичных значений.
Чтобы использовать функции, нам нужно импортировать модуль, как показано ниже:
Функции и реализация
Различные арифметические операции могут выполняться с десятичными или числовыми данными для улучшения результата.
Мы можем определить числа с десятичной запятой, используя decimal.Decimal() function как показано ниже.
Описанные ниже функции помогают нам выполнять арифметические операции с десятичной запятой эффективно и с большой скоростью.
Функция exp() — вычисление экспоненты
Функция exp() function вычисляет значение экспоненты, то есть e ^ x конкретного числа переданной десятичной точки.
Обратите внимание, что общее количество цифр в нашем выводе равно 5. Это из-за значения точности, которое мы здесь установили.
Следует помнить, что значение точности применяется, когда вы выполняете математические операции с двумя десятичными знаками, а не когда вы напрямую инициируете переменную со значениями, как показано с переменной «no_math» выше.
Функция sqrt() — квадратный корень
Функция sqrt() вычисляет и возвращает значение квадратного корня из переданного десятичного числа.
Снова обратите внимание, как объявленное значение содержит полное десятичное число, в то время как вычисленное значение соответствует нашему набору точности из 3 цифр.
3 Логарифмические функции
Модуль предоставляет нам следующие функции для вычисления логарифмических значений чисел с десятичной запятой:
Функция decimal.ln() function возвращает значение натурального десятичного числа, как показано ниже.
Функция decimal.log10() используется для вычисления значения журнала по основанию 10 переданного ей десятичного числа.
Функция compare()
Функция decimal.compare() function сравнивает два числа с десятичной запятой и возвращает значения в зависимости от условий следующим образом:
Функция copy_abs()
Функция decimal.copy_abs() function возвращает абсолютные значения переданного ей десятичного числа со знаком.
Максимальные и минимальные
Десятичный модуль содержит следующие функции для вычисления минимального и максимального значений десятичной запятой.
Логические операции с десятичным модулем
Decimal содержит набор встроенных функций для выполнения логических операций с десятичными числами, таких как AND, OR, XOR и т. Д.
Модуль decimal позволяет устранить недостатки, которые иногда возникают при работе с встроенными числами типа float, а именно:
Начнем с того, что некоторые числа типа float не могут быть точно представлены в двоичной системе счисления, например:
Однако, числа типа Decimal всегда ведут себя как истинные десятичные дроби:
Конечно, такая запись простого выражения кажется неоправданно громоздкой. Но в некоторых ситауциях такая «громоздкость» – это мелочь в сравнении с проблемами, которые могут возникнуть в отсутствии необходимой точности.
Очень часто с числами типа float проблематично выполнять операции сравнения:
Поэтому использование лишь чисел типа float очень затрудняет разработку финансовых приложений.
Числа типа float имеют фиксированную точность, в то время как числа типа Decimal настраиваемую:
Кроме того модуль decimal позволяет полность контролировать все вычисления и их точность, т.е. не просто задавать нужное количество цифр после запятой, а именно перехватывать ситуации в которых эта точность нарушается. Что позволяет не просто блокировать неточные операции, но и строить приложения, которые полностью соответствуют Общей спецификации десятичной арифметики.
Устройство модуля decimal
Модуль decimal базируется на трех понятиях: десятичное число, контекст вычислений и сигналы.
Десятичное число в данном модуле относится к немутирующему (неизменяемому) типу данных, т.е. как и все основные числа в Python они не могут быть изменены напрямую. Десятичное число может обладать знаком, состоять из мантисы и экспоненты. Для сохранения значимости конечные нули не усекаются. Такие специальные значения, как -inf, inf и nan так относятся к десятичным числам. В данном модуле значения \(-0\) и \(+0\) считаются различными.
Контекст вычислений определяет точность, правила округления, ограничения на экспоненты, флаги результатов операций и средства активации исключений.
Сигналы – это специальные условия, которые возникают в процессе вычислений. Опционально, данные условия могут рассматриваться, как исключительные (вызывать ошибку) или информационные, а могут и просто игнорироваться.
Каждый сигнал обладает отдельным флагом и активатором его перехвата. При возникновении сигнала, его флаг устанавливается в единицу и если активатор его перехвата так же установлен в единицу, то вызывается исключение. Следует помнить, что значения флагов не сбрасываются после обработки исключений, т.е. каждый раз их значения необходимо сбрасывать.
Как использовать модуль?
Все начинается с импорта модуля:
Я думаю, что вы уже заметили какими громоздкими становятся выражения при использовании данного модуля, поэтому данный способ импорта, является наиболее удобным (хотя и не обязательным).
Следующим шагом (опять же необязательным) может быть просмотр текущего контекста с помощью метода getcontext() :
Если же передать число типа float, то следует иметь в виду, что число типа Decimal будет создано, не из того числа, которое вы видите, а из того числа, которое хранится в компьютере. Попытаемся сделать число Decimal из постоянной Планка:
Появившийся «хвост» числа как раз и демонстрирует нам то, что с ним происходит после погружения в двоичный мир компьютера и обратного преобразования в десятичную систему счисления. А именно то что конечная десятичная дробь в двоичной системе счисления может быть бесконечной, что приводит к неизбежному округлению и следовательно к потере точности:
Подобного поведения можно избежать если передать Decimal() вместо числа, его строковое представление:
Можно использовать встроенную функцию str() :
А можем и не пользоваться, так как числа типа Decimal поддерживают все математические операции:
В математических выражениях мы можем комбинировать числа типа int с числами типа Decimal:
Есть еще один любопытный способ создания – передача числа в виде кортежа:
Значение prec не изменяет количество значимых цифр вводимого числа, но обязательно изменит его после выполнения математических операций:
Надо сказать, что по началу модуль decimal реально кажется громоздким и неуклюжим, но благодаря тому, что он прекрасно поддерживает большинство встроенных функций, это ощущение довольно быстро пропадает. Ниже приведены несколько примеров, которые позволяют в этом убедиться.
Как-то так можно вычислить основание натурального логарифма:
В общем, после импорта библиотеки, числа типа Decimal ведут себя точно так же как встроенные числовые типы, т.е. все привычные действия могут выполняться практически так как мы к этому привыкли. Например, если нам понадобится список десятичных чисел фиксированной длинны то мы можем создать его как-то так с помощью генератора:
Некоторые математические функции реализованы как методы класса Decimal:
Округлить число до необходимого количества значащих цифр можно с помощью метода quantize() :
Так же в соответствии со стандартом модуль предоставляет два готовых контекста BasicContext и ExtendedContext:
Если приглядеться к BasicContext, то мы увидим что у него установлено гораздо больше сигналов ошибок, что может быть полезно при отладке приложений:
Для мониторинга ошибок или других интересующих нюансов вычислений контексты имеют сигналы, которые отслеживаются с помощью флагов. Данные флаги остаются активными до явного сброса, поэтому для повторного отслеживания интересующих сигналов их нужно явно сбросить. Посмотрите на параметр flags до и после вычислений:
В конечном итоге в списке флагов мы видим, что выполнялось деление на \(0\), что результат был округлен (т.е. цифры за пределами prec были отброшены) и что результат является не точным (т.к. отброшенные цифры не были нулевыми). Как видите информация довольно полезная, но ее нельзя снова отследить пока флаги не сброшены. А сбросить их позволяет метод clear_flags() :
Активировать отдельные ловушки можно с помощью параметра traps :
После установки флага Rounded в активное значение команда Decimal(1)/Decimal(16) выполнилась без ошибки, потому что результат операции входит в диапазон точности prec и следовательно не нуждается в округлении. А вот результат команды Decimal(1)/Decimal(17) должен быть округлен, а значит вызывать ошибку.
Таким образом мы можем перехватывать множество сигналов, что позволяет создавать очень надежные приложения.
Объект Decimal
Помимо прочего строками могут быть десятичные цифры в виде строк Юникода, в том числе и других алфавитов:
Числа типа float переводятся в числа типа Decimal без потерь, т.е. именно так как они хранятся в памяти компьютера:
Только если значение сигнала FloatOperation установлено в единицу то преобразование приведет к ошибке (по умолчанию сигнал отключен):
Аргумент context позволяет задать поведение для тех случаев когда строка является искаженной. По умолчанию, этот параметр установлен в значение None, что приводит любую невалидную строку в значение NaN:
В случае если параметр context перехватывает сигнал InvalidOperation, то вместо значения NaN появляется сообщение об ошибке:
Ну а значениями данного параметра могут быть только контексты вычислений:
Числа типа Decimal являются немутирующими (неизменяемыми) объектами, т.е. могут быть ключами в словарях:
Числа типа Decimal во многом могут использоваться точно так же как и числа типа int и float. Есть лишь несколько незначительных отличий. При выполнении оператора ‘%’ (остаток от деления) к числам типа Decimal знак результата будет таким же как у делимого, а не делителя:
Это различие объясняется тем что числа типа Decimal выполняют требования общей спецификации десятичной арифметики, в то время как встроенные типы int и float реализованы на языке C и соответственно выполняют требования которые предъявляются к данному языку.
Числа типа Decimal и float, а так же рациональные дроби fractions.Fraction, как правило, не могут присутствовать вместе в одном математическом выражении. Однако, операции сравнения могут выполняться между числом Decimal и другим числом любого типа (если только не установлен сигнал FloatOperation):
Методы объекта Decimal
Объекты типа Decimal обладают множеством специализированных методов.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Эта операция не зависит от контекста, т.к. значения NaN включены в общий порядок сравнения. Но если второй операнд не может быть точно представлен то Python реализованный на языке C может вызвать исключение InvalidOperation.
Эта операция не зависит от контекста, т.к. значения NaN включены в общий порядок сравнения. Но если второй операнд не может быть точно представлен то Python реализованный на языке C может вызвать исключение InvalidOperation.
Параметр context может принимать объект любого контекста вычислений.
Некоторые числа типа float, не имеют точного представления в двоичной системе (являются бесконечными дробями) поэтому в памяти компьютера они всегда хранятся с некоторой погрешностью:
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Если операнд равен \(0\), то возвращается Decimal(‘-Infinity’) и вызывается исключение DivisionByZero. Если операнд равен бесконечности, то так же возвращается бесконечность.
Параметр context может принимать объект любого контекста вычислений.
Логические операнды
Числа типа Decimal могут восприниматься как логические значения если их знак и экспонента равны \(0\), а все остальные цифры состоят только из \(0\) и \(1\). Например, число Decimal((0, (1, 1, 0, 1), 0)) или Decimal(‘1101’) можно спокойно считать логическими и передавать их логическим функциям.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Сравнения «больше/меньше»
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Параметр context может принимать объект любого контекста вычислений.
Приращения аргументов
В отличие от других опраций округления, данный метод никогда не сигнализирует о потере точности.
Объекты контекста
Контексты – это среды в которых выполняются арифметические операции. Контексты определяют с какой точностью будут выполняться вычисления, как будет происходить округление чисел, какие сигналы рассматривать как исключения, а какие игнорировать.
Каждый поток имеет свой собственный контекст, который можно изменить или установить с помощью функций getcontext() или setcontext()
Если какое-то поле не указано, то оно по умолчанию заменяется на значение из контекста DefaultContext. Если поле флагов не указано или отсутствует, то это приводит к очистке флагов.
rounding позволяет задать режим округления.
Поля traps и flags являются списками с сигналами и статусами их отслеживания.
Значение clamp = 1 обеспечивает совместимость с числами с плавающей точкой фиксированной длинны, которые указаны в IEEE 754.
Методы класса Context
Методы класса Context также как и методы класса Decimal могут принимать числа типа int.
Руководство и примеры использования модуля decimal.
Обычное начало использования модуля десятичных чисел начинается с импорта модуля decimal и просмотр текущего контекста с помощью decimal.getcontext() и при необходимости, установка новых значений для необходимой точности и округления:
Если сигнал decimal.FloatOperation перехватывает случайное смешивание десятичных чисел и значений с плавающей запятой в конструкторах или в сравнениях, то вызывается исключение:
Значимость нового десятичного числа определяется исключительно количеством введенных цифр. Точность контекста и округление вступают в игру только во время арифметических операций.
Если внутренние пределы числа версии языка C превышены, построение десятичного числа вызывает исключение InvalidOperation :
Десятичные дроби хорошо взаимодействуют с большей частью Python.
А некоторые математические функции также доступны для класса decimal.Decimal() в качестве методов:
Метод Decimal.quantize() округляет число до фиксированной степени. Этот метод полезен для денежных приложений, которые часто округляют результаты до фиксированной точности:
Как показано выше, функция decimal.getcontext() получает доступ к текущему контексту и позволяет изменять настройки. Этот подход отвечает потребностям большинства приложений.
Запись флагов показывает, что рациональное приближение к числу Pi было округлено, цифры за пределами контекста были отброшены и что результат является неточным, т. к. некоторые из отброшенных цифр были ненулевыми.
Отдельные ловушки traps устанавливаются с помощью словаря в поле ловушек контекста:
После установки флага Rounded в активное значение операции Decimal(1)/Decimal(16) выполнилась без ошибки, потому что результат операции входит в диапазон точности prec и следовательно не нуждается в округлении. А вот результат операции Decimal(1)/Decimal(17) должен быть округлен, а значит вызовет ошибку.
Методы десятичного объекта Decimal().
Содержание:
Decimal.adjusted() :
Возвращает скорректированный показатель степени числа, при котором слева от десятичной точки остается только одна цифра. Полезен для определения самой значимой цифры числа.
Decimal.as_tuple() :
Decimal.canonical() :
Возвращает число в канонической форме. Учитывая, что Decimal() и так возвращает число в канонической форме, то применение данного метода не приведет к другим изменениям аргумента.
Decimal.compare(other, context=None) :
Параметр context может принимать объект любого контекста вычислений.
Decimal.compare_signal(other, context=None) :
Параметр context может принимать объект любого контекста вычислений.
Decimal.compare_total(other, context=None) :
Аналогичен методу Decimal.compare() но позволяет выполнять сравнение не на основе значения чисел, а на основе их абстрактного представления.
Decimal.compare_total_mag(other, context=None) :
Decimal.conjugate() :
Возвращает исходный объект без каких-либо изменений, как есть. Данный метод реализован только для соответствия спецификации.
Decimal.copy_abs() :
Возвращает абсолютное значение числа. Данная операция не зависит от контекста, не изменяет флаги, не выполняет округления.
Decimal.copy_negate() :
Decimal.copy_sign(other, context=None) :
Decimal.exp(context=None) :
Параметр context может принимать объект любого контекста вычислений.
Decimal.from_float(f) :
Преобразует число типа float в число типа decimal.Decimal() как есть, т.е. так как оно представлено в памяти компьютера.
Decimal.fma(other, third, context=None) :
Параметр context может принимать объект любого контекста вычислений.
Decimal.is_canonical() :
Decimal.is_finite() :
Decimal.is_infinite() :
Возвращает True если аргумент является положительной или отрицательной бесконечностью и False во всех остальных случаях.
Decimal.is_nan() :
Возвращает True если аргумент является NaN или сигнальным sNaN и False` во всех остальных случаях.
Decimal.is_normal(context=None) :
Decimal.is_qnan() :
Возвращает True если аргумент является обычным NaN и False во всех остальных случаях.
Decimal.is_signed() :
Decimal.is_snan() :
Decimal.is_subnormal() :
Возвращает True если аргумент является числом слишком маленьким для текущей точности и False во всех остальных случаях.
Decimal.is_zero() :
Возвращает True если аргумент является нулем положительным или отрицательным и False во всех остальных случаях.
Decimal.ln(context=None) :
Параметр context может принимать объект любого контекста вычислений.
Decimal.log10(context=None) :
Параметр context может принимать объект любого контекста вычислений.
Decimal.logb(context=None) :
Возвращает целое число, которое является показателем величины самой значимой цифры операнда.
Параметр context может принимать объект любого контекста вычислений.
Логические операции:
Числа типа Decimal могут восприниматься как логические значения если их знак и экспонента равны 0, а все остальные цифры состоят только из0 и 1. Например, число Decimal((0, (1, 1, 0, 1), 0)) или Decimal(‘1101’) можно спокойно считать логическими и передавать их логическим функциям.
Decimal.logical_and(other, context=None) :
Логическое И двух операндов.
Параметр context может принимать объект любого контекста вычислений.
Decimal.logical_invert(context=None) :
Логическое НЕ, поразрядное инвертирование битов.
Параметр context может принимать объект любого контекста вычислений.
Decimal.logical_or(other, context=None) :
Логическое ИЛИ двух операндов.
Параметр context может принимать объект любого контекста вычислений.
Decimal.logical_xor(other, context=None) :
Логическое ИСКЛЮЧАЮЩЕЕ ИЛИ двух операндов.
Параметр context может принимать объект любого контекста вычислений.
Операции сравнения.
Decimal.max(other, context=None) :
Возвращает наибольший аргумент. Округление указанное в контексте выполняется перед возвращением результата.
Параметр context может принимать объект любого контекста вычислений.
Decimal.min(other, context=None) :
Возвращает наименьший аргумент. Округление указанное в контексте выполняется перед возвращением результата.
Параметр context может принимать объект любого контекста вычислений.
Decimal.max_mag(other, context=None) :
Возвращает больший аргумент, но сравниваются не сами аргументы, а их абсолютные значения. Округление указанное в контексте выполняется перед возвращением результата.
Параметр context может принимать объект любого контекста вычислений.
Decimal.min_mag(other, context=None) :
Возвращает меньший аргумент, но сравниваются не сами аргументы, а их абсолютные значения. Округление указанное в контексте выполняется перед возвращением результата.
Параметр context может принимать объект любого контекста вычислений.
Приращение аргументов.
Decimal.next_minus(context=None) :
Возвращает наибольшее число в указанном контексте, которое меньше чем данный операнд.
Decimal.next_plus(context=None) :
Возвращает наименьшее число в указанном контексте, которое больше чем данный операнд.
Decimal.next_toward(other, context=None) :
Decimal.normalize(context=None) :
Возвращает число к канонической форме.
Decimal.number_class() :
Возвращает строку описывающую класс операнда.
Decimal.quantize(exp, rounding=None, context=None) :
Возвращает округленное значение первого операнда с показателем степени второго операнда.
Также в отличие от других операций, квантование никогда не сигнализирует о потоке, даже если результат является ненормальным и неточным.
Decimal.radix() :
Decimal.remainder_near() :
Возвращает остаток от деления, но с таким знаком, который позволяет минимизировать его абсолютное значение.
Decimal.rotate(other, context=None) :
Decimal.same_quantum(other, context=None) :
Decimal.scaleb(other, context=None) :
Устанавливает показатель степени первого операнда в значение второго операнда, который должен быть целым числом.
Decimal.shift(other, context=None) :
Decimal.sqrt(context=None) :
Возвращает квадратный корень числа.
Decimal.to_eng_string(context=None) :
Возвращает строковое представление числа в инженерной форме.
Decimal.to_integral(rounding=None, context=None) :
Эквивалентен методу Decimal.to_integral_value() и присутствует только для соответствия спецификации.
Decimal.to_integral_exact(rounding=None, context=None) :
Числа: целые, вещественные, комплексные
Числа в Python 3: целые, вещественные, комплексные. Работа с числами и операции над ними.
Целые числа (int)
Числа в Python 3 ничем не отличаются от обычных чисел. Они поддерживают набор самых обычных математических операций:
Также нужно отметить, что целые числа в python 3, в отличие от многих других языков, поддерживают длинную арифметику (однако, это требует больше памяти).
Битовые операции
Над целыми числами также можно производить битовые операции
x | y | Побитовое или |
x ^ y | Побитовое исключающее или |
x & y | Побитовое и |
x > y | Битовый сдвиг вправо |