§ 8.4. Действительный тип float. Программирование линейных алгоритмов. Импорт модулей. Функции модуля math

Школьный курс C++
Содержание

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

Действительные (вещественные) числа представлены в python типом float. Этот тип аналогичен типу double в C++. Таким образом, данный тип, в отличие от типа int, имеет фиксированную ширину. Максимальное и минимальное значение переменной данного типа:

max = 1.7976931348623157e+308,  
min = 2.2250738585072014e-308 

Не взирая на величину порядка, количество точных знаков в мантиссе числа ограничено 16 десятичными разрядами, сверх которых будет накапливаться неточность. Из этого следует важный вывод о том, что нельзя применять данный тип для точных вычислений. Однако для решения большинства инженерных задач такой точности вполне достаточно. Если же требуется выполнять вычисления с действительными числами произвольной точности, то для этого в python существуют два способа – это использование типов fractions и decimal, с которыми мы познакомимся позднее.
Для преобразования объекта в действительное число используется функция float(). В случае строки, объект, по внешнему виду, должен представлять действительный литерал с фиксированной или плавающей точкой:

>>> d1 = float(input('d1 = '))
d1 = 5.2
>>> d2 = float('0.3')
>>> d1 / d2
17.333333333333336

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

import math
f = math.pi
print(f.as_integer_ratio())

Вывод:

(884279719003555, 281474976710656)

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

Огромное количество полезных функций находится не в ядре языка python, а в его богатой стандартной библиотеке, которая представляет собой хранилище модулей. Когда в программе требуется получить необходимое расширение функционала python – импортируется необходимый модуль языка. Собственно, разработчик может создавать и свои собственные модули библиотечного характера, а также использовать модули других разработчиков. Создание модулей и объединение их в пакеты мы будем обсуждать в старших классах.
Чтобы функции внешнего модуля стали доступными в модуле программы, его необходимо импортировать. Существует несколько способов импорта модулей.
В предыдущей программе мы импортировали модуль с математическими функциями math. Модуль импортируется с помощью ключевого слова import, после которого, через запятую, перечисляются имена импортируемых модулей. Модули – это классы, поэтому члены класса (поля и методы) вызываются с помощью dot-нотации. Т. е. сначала указывается имя модуля, затем, после точки, функция этого модуля. Например:

import math
print(math.sqrt(2))
print(math.hypot(3, 5))
import calendar
print(calendar.month(2022, 1))
import os
print(os.uname())

Вывод:

1.4142135623730951
5.8309518948453
    January 2022
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
31

posix.uname_result(sysname='Linux', 
nodename='sakhastro', 
release='5.12.12-300.fc34.x86_64', 
version='#1 SMP Fri Jun 18 14:30:51 UTC 2021', 
machine='x86_64')

Такой способ не очень удобен, т. к. каждый раз приходится обращаться к имени модуля. Чтобы не использовать имя модуля, можно включить все имена, которые определенны в этом модуле, как-будто они принадлежат самой программе.

from math import *
print(sqrt(2) * pi)
c = sqrt(3**2 + 7**2)
print('{:.2f}'.format(c))

Именно так мы и поступали в прошлом учебном году, когда изучали модуль Turtle. Но это не очень хорошая идея, если вспомнить о переопределении имен объектов, которое может произойти, в случае совпадения имен (об этом мы упоминали на прошлом уроке). Поэтому лучше перечислить те функции, которые будут использоваться в данной программе из импортированного модуля:

from math import sqrt, pi

Наконец, предотвратить переопределение имени может помочь алиасинг (подмена) имени. Например:

import turtle as t
t.reset()
t.fd(100)
t.left(45)
Для того, чтобы узнать какие имена определены в данном модуле, необходимо вызвать функцию 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']

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

Модуль math предоставляет доступ к большому числу известных математических функций, определенных стандартом языка Си. В таблице ниже перечислены некоторые функции и константы этого модуля.

Функция Описание
sqrt(x) квадратный корень x
isqrt(x) наибольшее целое число a такое, что a² ≤ n.
pow(a, b) возведение в степень, ab
hypot(a, b) гипотенуза
pi число π
e число e
exp(x) экспонента, ex
factorial(x) факториал x, x!
gcd(a, b) НОД(a, b) наибольший общий делитель (аргументов м. б. > 2)
lcm(a, b) НОК(a, b) наименьшее общее кратное (аргументов м. б. > 2)
log1p(x), log10(x), log(x[, base]) логарифмические ln(1+x), lg и logbase
sin(x), cos(x), tan(x) тригонометрические, x в радианах
asin(x), acos(x), atan(x) тригонометрические, возвращают радианы
atan2(y, x) Вычисляет арктангенс с учетом знаков аргументов для правильного определения квадранта (угол phi в полярных координатах)
degrees(x) радианы → градусы
radians(x) градусы → радианы
fabs(x) модуль x, |x|
copysign(x, y) возвращает x со знаком y
fsum(iterable) суммирует элементы последовательности с сохранением точности для действительных чисел
ceil(x) округляет число вверх (“потолок”) до ближайшего целого
trunc(x) округляет число x в сторону 0 (отбрасывает дробную часть)

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

Программирование линейных алгоритмов

Программа, в которой нет инструкций управления (ветвления и циклы) и она составляется в одном модуле (файле), реализует линейный алгоритм. Линейным он называется потому, что все инструкции программы от начала и до конца выполняются последовательно. В большинстве своем, такие программы являются частью больших и более сложных программ. Разработка программ такого типа позволяет получить навыки работы с различными типами данных, умение создавать дружественные интерфейсы программ и составлять арифметические выражения на языке программирования python. Условно, такую программу можно разделить на несколько частей:

  • Организация диалога и ввод исходных данных
  • Вычисление арифметических выражений
  • Форматированный вывод результатов
Рассмотрим пример линейной программы на примере следующей задачи.
Задача 1. Даны стороны треугольника a, b и c. По формуле Герона определить его площадь, длину высоты ha, а также радиусы вписанной и описанной окружности – r и R. Для рассчетов используйте следующие формулы:
                
Конкретно в этой задаче, даются классические формулы в математической нотации. В других задачах, прежде чем составлять алгоритм, требуется произвести анализ задачи и построить математическую модель. Создание несложных программ – это многоступенчатый процесс, который повторяет все этапы каскадной модели разработки программного обеспечения. Методологии разработки ПО, их достоинства и недостатки будут обсуждаться в следующем учебном году. Здесь же перечислим основные этапы каскадной модели:
  • Постановка задачи
  • Проектирование
  • Конструирование
  • Реализация
  • Тестирование и отладка
  • Инсталляция
Постановка задачи – это то условие, которое нами было получено. В более широком понимании – здесь выдвигаются требования заказчика, обсуждаются общие подходы к решению задачи.
На этапе проектирования создается математическая модель. Выясняется, какие требуются исходные данные, чтобы модель была работоспособной, подбирается необходимый математический аппарат, чтобы задача решалась наиболее эффективно. В задачах школьного курса на это “намекает” условие самой задачи, которое нужно очень внимательно прочитать. Часто сразу становится ясным как решать данную задачу – в уме зреет алгоритм её решения.
Формулы в классической математической нотации должны быть представлены в линейной нотации, в виде строки. Для этого применяются арифметические операции языка и круглые скобки. Все числовые типы поддерживают следующие операции (опущены операции для комплексных чисел):

Операция Описание
x + y сумма x и y
x - y разница x и y
x * y произведение x и y
x / y частное x и y; рез. float
x // y частное x и y; рез. int
x % y остаток x / y
-x унарный минус
+x унарный плюс
x ** y x в степени y

На этапе конструирования создается алгоритм решения задачи на основе полученной на предыдущем этапе математической модели. Для наглядного представления могут создаваться блок-схемы всей задачи или отдельных её подзадач. Существуют и иные способы представления алгоритма, например, с помощью унифицированного языка моделирования (UML). Подбираются библиотеки, кодируются отдельные модули. Блок-схема нашей программы может выглядеть так, как показано на рис. ниже.
Реализация – это основной этап создания программы. На этом этапе составляется программа на базовом языке программирования и производится компиляция исходного кода программы в исполняемый машинный код. Наша программа на языке программирования python может быть составлена следующим образом:

Программа 8.4.1
#============= 1 ===============#
from math import sqrt
a = int(input('a = '))
b = int(input('b = '))
c = int(input('c = '))
#============= 2 ===============#
p = (a + b + c) / 2
S = sqrt(p * (p - a) * (p - b) * (p - c))
h_a = 2 * S / a
R = a * b * c / 4 / S
r = 2 * S / 2 / p
#============= 3 ===============#
print('S   = {:>5.2f}'.format(S))
print('h_a = {:>5.2f}'.format(h_a))
print('R   = {:>5.2f}'.format(R))
print('r   = {:>5.2f}'.format(r))

Вывод:

a = 10
b = 5
c = 7
S   = 16.25
h_a =  3.25
R   =  5.39
r   =  1.48

Это не единственный вариант составления программы. Именно поэтому преподаватель всегда “вычислит” недобросовестных учеников. Что может отличать одну такую простую программу от её другой реализации? Как ни странно – программирование творческий процесс и у каждого разработчика есть свой “конёк” (стиль, если хотите). Например, для идентификаторов используют не буквы, а слова, при этом, существуют традиции для написания имен переменных (о них мы рассказывали ранее). В данной задаче можно обойтись и без импорта модуля, заменив функцию sqrt на операцию **. Единственное ограничение – это то, что имена переменных должны соответствовать именам в условии задачи. Условие нашей задачи не предоставляет какого-то большого выбора, но, тем не менее, вывод можно было бы оформить совершенно иначе! К тому же, если вы воспользовались чужой реализацией, то по крайней мере – вы должны её объяснить. Иначе ваше решение точно не будет принято!
На следующем этапе проводится тестирование и отладка. Запуск программы на выполнение должен показать насколько данные, полученные программой, соответствуют ранее составленной математической модели. И, в целом, работа программы должна подчиняться известным свойствам алгоритма о которых мы говорили ранее. Исправляются синтаксические или семантические ошибки, неверно составленный алгоритм.
Программы составленные на языке python не требуют инсталляции, Но под инсталляцией понимается внедрение продукта в эксплуатацию. В более широком смысле этот этап включает не только внедрение, но и продвижение продукта и его сопровождение.

Приложение

Примеры решения задач
Вопросы
Темы сообщений
Задания А
Задания Б
Задания С
Ссылки
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.


Обсуждение закрыто.