§5. Тип с плавающей точкой float. Импорт модулей. Функции модуля math. Числовые типы fractions и decimal

Действительный тип float

В python значения с плавающей точкой представлены тремя типами float, complex и библиотечным типом decimal. Тип float представляет действительные числа двойной точности и соответствует типу double в C++, это означает, что точность таких чисел будет достигать 16 десятичных разрядов в дробной части. Информацию о точности и внутреннем представлении чисел с плавающей точкой для машины, на которой работает программа, можно получить при подключении модуля sys:

>>> import sys
>>> print(sys.float_info)
sys.float_info(max=1.7976931348623157e+308, 
max_exp=1024, max_10_exp=308, 
min=2.2250738585072014e-308, 
min_exp=-1021, min_10_exp=-307, 
dig=15, mant_dig=53, 
epsilon=2.220446049250313e-16, 
radix=2, rounds=1)

Примечание. Описание атрибутов находится здесь: https://docs.python.org/3/library/sys.html#sys.float_info
Если нужно соблюдать большую точность при вычислениях, то необходимо применять целый тип, поскольку при вычислениях с типом float точность будет теряться. Причины этого заключаются в методе представления действительных чисел в памяти компьютера, отличающимся от представления целых чисел. Такое явление общее для всех языков программирования. Библиотечный тип decimal может обеспечить произвольную точность (по умолчанию, до 28 знаков в числе с фиксированной точкой, см. ниже).
Для преобразования к типу float используется соответствующая стандартная функция float(). При преобразовании из строки, строковый литерал должен, по внешнему виду, соответствовать действительному литералу (он может быть представлен как число с фиксированной точкой, так и в экспоненциальной форме).

Комплексные числа

Тип complex является для python базовым арифметическим типом (помимо int и float).
Примечание. Ко́мплексное (или компле́ксное) число — это число вида a + bj, где a и b — действительные числа, а j — мнимая единица (величина, для которой выполняется равенство: j2 = − 1). (Вики).
Получить комплексное число можно при помощи конструктора complex([real[, imag]]). Например:

>>> complex()
0j
>>> complex(3, 5)
(3+5j)

Литералы комплексных чисел представлены действительной и мнимой частью, которая объединяется знаками "+" или "-". За мнимой частью следует символ j.
Для работы с комплексными числами доступны следующие стандартные функции и операции: bool, real, imag, +, -, *, /, abs(), conjugate(), == и !=. С комплексными числами нельзя использовать функции модуля math, но можно использовать специальные функции cmath (соответствующие стандарту языка C).
Получить доступ к действительной части числа можно с помощью атрибута real, а ко мнимой с помощью атрибута imag:

>>> a = complex(2, 3)
>>> a.imag
3.0
>>> a.real
2.0

Функции модуля math

После импорта модуля math:

import math

станут доступными многочисленные функции математического модуля. Наиболее часто используемые функции приведены в таблице ниже. Обратите внимание, что некоторые функции можно представить и с помощью стандартных операций (и функций). Например, извлечения квадратного корня:

>>> print(2**0.5)
1.4142135623730951
>>> print(pow(2, 0.5))
1.4142135623730951
>>> import math
>>> print(math.sqrt(2))
1.4142135623730951

Результат будет одинаков.

Функции модуля math
Функция Описание
sqrt(x) квадратный корень x
pow(a, b) возведение в степень, ab
hypot(a, b) гипотенуза
pi число π
e число e
exp(x) экспонента, ex
gcd(a, b) НОД(a, b) наибольший общий делитель
log(x), log10(x), log(x[, base]) логарифмические, ln, lg и logbase
sin(x), cos(x), tan(x) тригонометрические, x в радианах
asin(x), acos(x), atan(x) тригонометрические, возвращают радианы
degrees(x) радианы → градусы
radians(x) градусы → радианы
fabs(x) модуль вещественного x
copysign(x, y) возвращает x со знаком y

Импорт модулей

Python позволяет поместить классы, функции или данные в отдельные файлы и использовать их в других программах. Такой файл называется модулем. Все имена внутри модуля называются атрибутами — такими, например, как функции и переменные. Помимо модулей, создаваемых разработчиками, Python распространяется с собственной библиотекой стандартных модулей. Эта библиотека включает в себя более 200 модулей, которые выполняют платформо-зависимую поддержку разнообразных задач. Полный список модулей можно посмотреть на странице документации Python: https://docs.python.org/3.6/py-modindex.html.
Для того, чтобы модуль стал доступен в программе необходимо в начале программы (или перед вызовом компоненты) обратиться к служебному слову import, например:

import math # Будет импортирован модуль с известными 
# математическими функциями
import turtle # Графический модуль "Черепашка"

Если модуль импортирован, то мы получаем доступ ко всем функциям, которые определены в этом модуле. Например:

>>> import math
>>> print(math.pi) # Вывести число pi
3.141592653589793
>>> 2 * math.sqrt(3) # вычислить 2 корня из 3
3.4641016151377544
import calendar
cal = calendar.month(2013, 9)
>>> print(cal)
   September 2013
Mo Tu We Th Fr Sa Su
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30

Варианты импорта:
Взятие непосредственно имени функции без упоминания имени модуля:

>>> from math import sqrt, sin, exp
>>> sqrt(2)
1.4142135623730951

Ещё один вариант импорта — включение всех имен, определенных в модуле:

>>> from turtle import *
>>> reset()

Само по себе это не является хорошей идеей, так как возможен конфликт имен разных модулей. Для предотвращения конфликта имен можно использовать создание алиаса (подмена имени):

>>> import turtle as t
>>> t.reset()

Примечание. Для того, чтобы узнать список имён, определённых в модуле, воспользуйтесь встроенной функцией dir(). Она возвращает отсортированный список строк:

>>> dir(math)
['__doc__', '__file__', '__loader__', '__name__', '__package__', 'acos', 
'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 
'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 
'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isfinite', 
'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 
'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 
'trunc']

Числовые типы fractions и decimal

decimal

Decimal представляет собой абстрактный тип (класс) в котором реализована арифметика действительных чисел произвольной точности в виде чисел с фиксированной точкой. В этом классе исправляется недостаток фундаментального действительного типа float, который накапливает неточность в виду того, что некоторые числа не имеют точного представления. Например:

>>> 1.1 + 2.2
3.3000000000000003

Примечание. По этой же причине действительные числа не корректно сравнивать с нулем.
По умолчанию доступна работа с 28 десятичными знаками, но может быть расширена до столь большого значения, сколько потребуется для решения поставленной задачи.
Десятичное число изменять нельзя. Оно имеет все атрибуты «обычного» числа. В добавок к этому, существуют следующие значения: Infinity, -Infinity (бесконечность), и NaN (не число). Стандарт также отличает -0 от +0.
Скорость работы с объектами Decimal не уступает скорости работы с фундаментальными типами. Чтобы получить объект Decimal необходимо импортировать модуль и использовать конструктор: Decimal([value[, context]]). Например:

>>> from decimal import *
>>> x = Decimal('2.1')
>>> y = Decimal('3.3')
>>> x * y
Decimal('6.93')
>>> y / x
Decimal('1.571428571428571428571428571')

Экземпляры класса Decimal могут быть построены из целых и действительных чисел, строк или кортежей. За «внешнее» представление числа типа decimal отвечает класс context. Для того, что бы узнать значения атрибутов этого класса по умолчанию необходимо вызвать функцию getcontext():

>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_UP, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])

Значение атрибутов:

  • prec (int) – количество цифр после десятичной точки
  • rounding – порядок округления
  • traps – список сигналов, которые возбуждают исключения в различных обстоятельствах (например, при попытке выполнить деление на ноль)
  • flags – список сигналов, свидетельствующих о начальном состоянии контекста (например, переполнение). Обычно аргумент flags не указывается.
  • Emin (int) – минимальное значения экспоненты
  • Emax (int) – максимальное значения экспоненты
  • capitals (int) – какой символ, 'E' или 'e', должен использоваться для обозначения экспоненты. По умолчанию имеет значение 1 ('E').
С помощью этой же функции можно задать или изменить существующий контекст. Например:

>>> getcontext().prec = 8
>>> Decimal(5) ** Decimal('0.5')
Decimal('2.2360680')
>>> getcontext().prec = 20
>>> Decimal(5) ** Decimal('0.5')
Decimal('2.2360679774997896964')

Decimal хорошо взаимодействует со многими стандартными функциями и операциями, а некоторые математические функции определены и для этого класса. Пример программы с использованием различных вещей приведен ниже:
Программа 5.1

from decimal import *
my_context = Context(prec = 50,
                     # Округление в сторону от нуля
                     rounding = ROUND_HALF_DOWN)
setcontext(my_context)
a = Decimal(input('a = '))
b = Decimal(input('b = '))
print('{:8s}{:2s}{:}'.format('a / b', '=', a / b))
print('{:8s}{:2s}{:}'.format('sqrt(a)', '=', a.sqrt()))
print('{:8s}{:2s}{:}'.format('a ** b', '=', a ** b))

Вывод программы:

a = 1.2
b = 0.7
a / b   = 1.7142857142857142857142857142857142857142857142857
sqrt(a) = 1.0954451150103322269139395656016042679054893899960
a ** b  = 1.1361269771988886910919752015764046368571990362488

Порядок округления:

  • ROUND_CEILING — Округление в сторону положительной бесконечности;
  • ROUND_DOWN — Округление в сторону нуля;
  • ROUND_FLOOR — Округление в сторону отрицательной бесконечности;
  • ROUND_HALF_DOWN — Округление в сторону от нуля;
  • ROUND_HALF_EVEN — То же, что и ROUND_HALF_DOWN, в большую сторону, если оно нечетное, а предыдущее перед ним больше 4;
  • ROUND_HALF_UP — То же, что и ROUND_HALF_DOWN, округляет число в сторону повышения, если после него идет число 5 или выше;
  • ROUND_UP — Округление в сторону от нуля;
  • ROUND_05UP — Округление в сторону от нуля, если последний значимый разряд содержит цифру 0 или 5, в противном случае округление выполняется в сторону нуля.
Полное руководство по данному классу находится в документации по адресу: https://docs.python.org/3/library/decimal.html

fractions

Абстрактный класс fractions призван реализовать арифметические вычисления с рациональными числами. Иными словами объект класса хранит числитель и знаменатель порознь, не производя деления, а вычисления производятся как операции с обыкновенными дробями. При этом сохраняется точность вычислений, т. е. решается проблема неточного представления чисел с плавающей точкой типом float. И числитель, и знаменатель представлен как целое число произвольной точности (это представление класс создает сам).
Экземпляр класса fractions может быть построен из пары целых чисел, числа типа float, из другого рационального числа, или из строки. Для начала работы с классом fractions необходимо импортировать модуль. Класс поддерживает любые арифметические операции. Покажем вышесказанное на примере:
Программа 5.2

from fractions import *
a = Fraction(input('a = '))
b = Fraction('11/15')
c = Fraction(123456789, 11111111)
d = Fraction(3.14)
print('d =', d, '\nb =', b, '\nc =', c)
print('a * b =', a * b)
print('d / 2 =', d / 2)
print('c % a =', c % a)

Вывод программы:

a = 25/3
d = 7070651414971679/2251799813685248 
b = 11/15 
c = 123456789/11111111
a * b = 55/9
d / 2 = 7070651414971679/4503599627370496
c % a = 92592592/33333333

Метод класса from_decimal позволяет создать экземпляр на основе объекта класса decimal:

>>> from decimal import *
>>> from fractions import *
>>> a = Decimal(3.3)
>>> a
Decimal('3.29999999999999982236431605997495353221893310546875')
>>> d = Fraction.from_decimal(a)
>>> d
Fraction(3715469692580659, 1125899906842624)

Метод класса limit_denominator лимитирует размер знаменателя дроби и, таким образом, позволяет находить рациональное приближение к заданному числу с плавающей точкой или восстанавливать рациональное представление числа с фиксированной точкой:

>>> from fractions import Fraction
>>> from math import pi, cos
>>> Fraction('3.1415926535897932').limit_denominator(1000)
Fraction(355, 113)
>>> Fraction(cos(pi/3))
Fraction(4503599627370497, 9007199254740992)
>>> Fraction(cos(pi/3)).limit_denominator()
Fraction(1, 2)
>>> Fraction(1.1).limit_denominator()
Fraction(11, 10)

Полное руководство по данному классу находится в документации по адресу: https://docs.python.org/3/library/fractions.html

Print Friendly, PDF & Email

Comments are closed