Главная страница

Питон для нормальных. Учебник Москва Базальт спо макс пресс 2018


Скачать 2.54 Mb.
НазваниеУчебник Москва Базальт спо макс пресс 2018
АнкорПитон для нормальных
Дата05.10.2022
Размер2.54 Mb.
Формат файлаpdf
Имя файлаsysoeva_sysoev_piton_dlya_normalnyh_ch1.pdf
ТипУчебник
#715174
страница8 из 14
1   ...   4   5   6   7   8   9   10   11   ...   14
благодаря чему каждый следующий рекурсивный вызов этой функции пользу- ется своим набором локальных переменных и за счёт этого работает корректно.
Оборотной стороной этого довольно простого по структуре механизма является то, что на каждый рекурсивный вызов требуется некоторое количество опера- тивной памяти компьютера, и при чрезмерно большой глубине рекурсии может наступить переполнение стека вызовов.
Вопрос о желательности использования рекурсивных функций в программи- ровании неоднозначен: с одной стороны, рекурсивная форма может быть струк- турно проще и нагляднее, в особенности, когда сам реализуемый алгоритм, по сути, рекурсивен. Кроме того, в некоторых декларативных или чисто функци- ональных языках (таких, как Пролог или Haskell) просто нет синтаксических средств для организации циклов, и рекурсия в них — единственный доступный механизм организации повторяющихся вычислений. С другой стороны, обычно рекомендуется избегать рекурсивных программ, которые приводят (или в некото- рых условиях могут приводить) к слишком большой глубине рекурсии. Так, ши- роко распространённый в учебной литературе пример рекурсивного вычисления факториала является, скорее, примером того, как не надо применять рекурсию,
так как приводит к достаточно большой глубине рекурсии и имеет очевидную реализацию в виде обычного циклического алгоритма.
4.6
Примеры решения заданий
Пример задачи 12 Напишите функцию, вычисляющую значения экспо- ненты по рекуррентной формуле e x
= 1 + x +
x
2 2!
+
x
3 3!
+ · · · =
P

n=0
x n
n!
. Ре- ализуйте контроль точности вычислений с помощью дополнительного параметра ε со значением по умолчанию (следует остановить вычисле- ния, когда очередное приближение будет отличаться от предыдущего менее, чем на 10

10
).
Реализуйте вызов функции различными способами:

4.6. Примеры решения заданий
107
• с одним позиционным параметром (при этом будет использовано значение по умолчанию);
• с двумя позиционными параметрами (значение точности будет пе- редано как второй аргумент);
• передав значение как именованный параметр.
Решение задачи 12
d e
f
E X P O N E N T A (x , eps =10**( -10)):
ex = 1 # будущий результат dx = x # приращение i = 2
#
номер приращения w
h i
l e
a b
s
( dx ) > eps :
ex = ex + dx dx = dx * x / i i = i + 1
r e
t u
r n
ex
#
Основная программа
A =
f l
o a
t
(
i n
p u
t
( ’Введите показатель экспоненты: ’ ))
p r
i n
t
( E X P O N E N T A ( A ))
p r
i n
t
( E X P O N E N T A (A , 10**( -4)))
p r
i n
t
( E X P O N E N T A ( x = A )
Пример задачи 13 Сделайте из функции процедуру (вместо того, что- бы вернуть результат с помощью оператора return, выведите его внут- ри функции с помощью функции print).
Решение задачи 13
d e
f
E X P O N E N T A (x , eps =10**( -10)):
ex = 1 # будущий результат dx = x # приращение i = 2
#
номер приращения w
h i
l e
a b
s
( dx ) > eps :
ex = ex + dx dx = dx * x / i i = i + 1
p r
i n
t
( ex )
#
Основная программа
A =
f l
o a
t
(
i n
p u
t
( ’Введите показатель экспоненты: ’ ))
E X P O N E N T A ( A )

108
Глава 4. Функции
4.7
Задания на функции
Задание 11 Выполнять одно задание в зависимости от номера в спис- ке:
(n-1)%10+1
, где n — номер в списке. Напишите функцию, вычисляю- щую значения одной из следующих специальных функций по рекуррент- ной формуле. Реализуйте контроль точности вычислений с помощью до- полнительного параметра ε со значением по умолчанию (следует оста- новить вычисления, когда очередное приближение будет отличаться от предыдущего менее, чем на 10

10
). Реализуйте вызов функции различны- ми способами:
• с одним позиционным параметром (при этом будет использовано значение по умолчанию);
• с двумя позиционными параметрами (значение точности будет пе- редано как второй аргумент);
• передав значение как именованный параметр.
Сделайте из функции процедуру (вместо того, чтобы вернуть резуль- тат с помощью оператора return, выведите его внутри функции с по- мощью функции print).
1. Косинус cos(x) = 1 −
x
2 2!
+
x
4 4!
− · · · =
P

n=0
(−1)
n x
2n
(2n)!
. Формула хорошо ра- ботает для −2π 6 x 6 2π, поскольку получена разложением в ряд Тейлора возле ноля. Для прочих значений x следует воспользоваться свойствами периодичности косинуса: cos(x) = cos(2 + 2πn), где n есть любое целое число, тогда cos(x) = cos(x%(2*math.pi)). Для проверки использовать функцию math.cos(x).
2. Синус sin(x) = x −
x
3 3!
+
x
5 5!
+ · · · =
P

n=0
(−1)
n x
2n+1
(2n+1)!
. Формула хорошо ра- ботает для −2π 6 x 6 2π, поскольку получена разложением в ряд Тейлора возле ноля. Для прочих значений x следует воспользоваться свойствами пе- риодичности косинуса: sin(x) = sin(2 + 2πn), где n есть любое целое число,
тогда sin(x) = sin(x%(2*math.pi))
. Для проверки использовать функцию math.sin(x)
3. Гиперболический косинус ch(x) = 1 +
x
2 2!
+
x
4 4!
+ · · · =
P

n=0
x
2n
(2n)!
. Для про- верки использовать функцию math.cosh(x).
4. Гиперболический косинус по формуле для экспоненты, оставляя только слагаемые с чётными n. Для проверки использовать функцию math.cosh(x).
5. Гиперболический синус sh(x) = x +
x
3 3!
+
x
5 5!
+ · · · =
P

n=0
x
2n+1
(2n+1)!
. Для про- верки использовать функцию math.sinh(x).

4.7. Задания на функции
109 6. Гиперболический синус по формуле для экспоненты, оставляя только сла- гаемые с нечётными n. Для проверки использовать функцию math.sinh(x).
7. Натуральный логарифм (формула работает при 0 < x 6 2):
ln(x) = (x − 1) −
(x − 1)
2 2
+
(x − 1)
3 3

(x − 1)
4 4
+ · · · =

X
n=1
(−1)
n−1
(x − 1)
n n
Чтобы найти логарифм для x > 2, необходимо представить его в виде ln(x) = ln(y · 2
p
) = p ln(2) + ln(y), где y < 2, а p натуральное число. Чтобы найти p и y, нужно в цикле делить x на 2 до тех пор, пока результат больше
2. Когда очередной результат деления станет меньше 2, этот результат и есть y, а число делений, за которое он достигнут – это p. Для проверки использовать функцию math.log(x).
8. Гамма-функция Γ(x) по формуле Эйлера:
Γ(x) =
1
x

Y
n=1 1 +
1
n

x
1 +
x n
Формула справедлива для x /
∈ {0, −1, −2, . . . }. Для проверки можно исполь- зовать math.gamma(x). Также, поскольку Γ(x + 1) = x! для натуральных x,
то для проверки можно использовать функцию math.factorial(x).
9. Функция ошибок, также известная как интеграл ошибок, интеграл вероят- ности, или функция Лапласа:
erf(x) =
2

π
Z
x
0
e

t
2
dt =
2

π

X
n=0
x
2n + 1
n
Y
i=1
−x
2
i
Для проверки использовать функцию scipy.special.erf(x).
10. Дополнительная функция ошибок:
erfc(x) = 1 − erf(x) =
2

π
Z

x e

t
2
dt =
e

x
2
x

π

X
n=0
(−1)
n
(2n)!
n!(2x)
2n
Для проверки использовать функцию scipy.special.erf(x).
Задание 12 (Танцы) Выполнять в каждом разделе по одному заданию в зависимости от номера в списке группы:
(n-1)%5+1
, где n — номер в списке.
1. два списка имён: первый — мальчиков, второй — девочек;
2. один список имён и число мальчиков, все имена мальчиков стоят в начале списка;

110
Глава 4. Функции
3. один список имён и число девочек, все имена девочек стоят в начале списка;
4. словарь, в котором в качестве ключа используется имя, а в каче- стве значения символ «м» для мальчиков и символ «ж» для девочек;
5. словарь, в котором в качестве ключей выступают символы «м» и
«ж», а в качестве соответствующих им значений — списки маль- чиков и девочек соответственно.
Проверьте работу функции на разных примерах:
• когда мальчиков и девочек поровну,
• когда мальчиков больше, чем девочек, и наоборот,
• когда есть ровно 1 мальчик или ровно 1 девочка,
• когда либо мальчиков, либо девочек нет вовсе.
Модифицируйте функцию так, чтобы она принимала второй необяза- тельный параметр — список уже составленных пар, участников кото- рых для составления пар использовать нельзя. В качестве значения по умолчанию для этого аргумента используйте пустой список. Проверьте работу функции, обратившись к ней:
• как и ранее (с одним аргументом), в этом случае результат должен совпасть с ранее полученным;
• передав все аргументы позиционно без имён;
• передав последний аргумент (список уже составленных пар) по име- ни;
• передав все аргументы по имени в произвольном порядке.
Задание 13 (Создание списков) Напишите функцию, принимающую от
1 до 3 параметров — целых чисел (как стандартная функция range).
Единственный обязательный аргумент — последнее число. Если поданы
2 аргумента, то первый интерпретируется как начальное число, второй
— как конечное (не включительно). Если поданы 3 аргумента, то тре- тий аргумент интерпретируется как шаг. Функция должна выдавать один из следующих списков:
1. квадратов чисел;
2. кубов чисел;
3. квадратных корней чисел;

4.7. Задания на функции
111 4. логарифмов чисел;
5. чисел последовательности Фибоначчи с номерами в указанных пре- делах.
Запускайте вашу функцию со всеми возможными вариантами по числу параметров: от 1 до 3.
Подсказка: проблему переменного числа параметров, из которых необязательным является в том числе первый, можно решить 2-мя способами. Во-первых, можно сопоставить всем параметрам нечисло- вые значения по умолчанию, обычно для этого используют специальное значение None. Тогда используя условный оператор можно определить,
сколько параметров реально заданы (не равны None). В зависимости от этого следует интерпретировать значение первого аргумента как: конец последовательности, если зада только 1 параметр; как начало, если за- даны 2 или 3. Во-вторых, можно проделать то же, используя синтаксис функции с произвольным числом параметров; в таком случае задавать значения по умолчанию не нужно, а полезно использовать стандартную функцию len, которая выдаст количество реально используемых пара- метров.
Задание 14 (Интернет-магазин) Решите задачу об интернет-торговле.
Несколько покупателей в течении года делали покупки в интернет- магазине. При каждой покупке фиксировались имя покупателя (строка)
и потраченная сумма (действительное число). Напишите функцию, рас- считывающую для каждого покупателя и выдающую в виде словаря по всем покупателям (вида имя:значение) один из следующих параметров:
1. число покупок;
2. среднюю сумму покупки;
3. максимальную сумму покупки;
4. минимальную сумму покупки;
5. общую сумму всех покупок.
На вход функции передаётся:
• либо 2 списка, в первом из которых имена покупателей (могут по- вторяться), во втором – суммы покупок;
• либо 1 список, состоящий из пар вида
(имя, сумма)
;
• либо словарь, в котором в качестве ключей используются имена, а в качестве значений — списки с суммами.

Глава 5
Массивы. Модуль numpy
Сам по себе «чистый» Python пригоден только для несложных вычислений.
Ключевая особенность Python — его расширяемость. Это, пожалуй, самый рас- ширяемый язык из получивших широкое распространение. Как следствие этого для Python не только написаны и приспособлены многочисленные библиотеки алгоритмов на C и Fortran, но и имеются возможности использования других программных средств и математических пакетов, в частности, R и SciLab, а так- же графопостроителей, например, Gnuplot и PLPlot.
Ключевыми модулями для превращения Python в математический пакет яв- ляются numpy и matplotlib.
numpy
— это модуль (в действительности, набор модулей) языка Python, до- бавляющая поддержку больших многомерных массивов и матриц, вместе с боль- шим набором высокоуровневых (и очень быстрых) математических функций для операций с этими массивами.
matplotlib
— модуль (в действительности, набор модулей) на языке про- граммирования Python для визуализации данных двумерной (2D) графикой (3D
графика также поддерживается). Получаемые изображения могут быть исполь- зованы в качестве иллюстраций в публикациях.
Кроме numpy и matplotlib популярностью пользуются scipy для специализи- рованных математических вычислений (поиск минимума и корней функции мно- гих переменных, аппроксимация сплайнами, вейвлет-преобразования), sympy для символьных вычислений (аналитическое взятие интегралов, упрощение матема- тических выражений), ffnet для построения искусственных нейронных сетей,
pyopencl
/pycuda для вычисления на видеокартах и некоторые другие. Возмож- ности numpy и scipy покрывают практически все потребности в математических алгоритмах.

5.1. Создание и индексация массивов
113
(a)
(b)
Рис. 5.1. Одномерный — (a) и двумерный — (b) массивы.
5.1
Создание и индексация массивов
Массив — упорядоченный набор значений одного типа, расположенных в па- мяти непосредственно друг за другом. При этом доступ к отдельным элемен- там массива осуществляется с помощью индексации, то есть через ссылку на массив с указанием номера (индекса) нужного элемента. Это возможно потому,
что все значения имеют один и тот же тип, занимая одно и то же количество байт памяти; таким образом, зная ссылку и номер элемента, можно вычислить,
где он расположен в памяти. Количество используемых индексов массива может быть различным: массивы с одним индексом называют одномерными, с двумя —
двумерными, и т. д. Одномерный массив («колонка», «столбец») примерно соот- ветствует вектору в математике (на рис. 5.1(а) a[4] == 56, т.е. четвёртый эле- мент массива а равен 56); двумерный — матрице (на рис. 5.1(b) можно писать
A[1][6] == 22
, можно A[1, 6] == 22). Чаще всего применяются массивы с од- ним или двумя индексами; реже — с тремя; ещё большее количество индексов встречается крайне редко.
Как правило, в программировании массивы делятся на статические и ди- намические. Статический массив — массив, размер которого определяется на момент компиляции программы. В языках с динамической типизацией таких,
как Python, они не применяются. Динамический массив — массив, размер кото- рого задаётся во время работы программы. То есть при запуске программы этот массив не занимает нисколько памяти компьютера (может быть, за исключе- нием памяти, необходимой для хранения ссылки). Динамические массивы могут поддерживать и не поддерживать изменение размера в процессе исполнения про- граммы. Массивы в Python не поддерживают явное изменение размера: у них, в отличие от списков, нет методов append и extend, позволяющих добавлять эле- менты, и методов pop и remove, позволяющих их удалять. Если нужно изменить размер массива, это можно сделать путём переприсваивания имени переменной,

114
Глава 5. Массивы. Модуль numpy обозначающей массив, нового значения, соответствующего новой области памя- ти, больше или меньше прежней разными способами.
Базовый оператор создания массива называется array. С его помощью можно создать новый массив с нуля или превратить в массив уже существующий список.
Вот пример:
f r
o m
numpy i
m p
o r
t
*
A = array ([0.1 , 0.4 , 3 , -11.2 , 9])
p r
i n
t
( A )
p r
i n
t
(
t y
p e
( A ))
В первой строке из модуля numpy импортируются все функции и константы.
Вывод программы следующий:
[0.1 0.4 3.
-11.2 9. ]

Функция array() трансформирует вложенные последовательности в много- мерные массивы. Тип элементов массива зависит от типа элементов исходной последовательности:
B = array ([[1 , 2 , 3] , [4 , 5 , 6]])
p r
i n
t
( B )
Вывод:
[[1 2 3]
[4 5 6]]
Тип элементов массива можно определить в момент создания с помощью име- нованного аргумента dtype. Модуль numpy предоставляет выбор из следующих встроенных типов: bool (логическое значение), character (символ), int8, int16,
int32
, int64 (знаковые целые числа размеров в 8, 16, 32 и 64 бита соответствен- но), uint8, uint16, uint32, uint64 (беззнаковые целые числа размеров в 8, 16, 32
и 64 бита соответственно), float32 и float64 (действительные числа одинарной и двойной точности), complex64 и complex128 (комплексные числа одинарной и двойной точности), а также возможность определить собственные типы данных,
в том числе и составные.
C = array ([[1 , 2 , 3] , [4 , 5 , 6]] , dtype =
f l
o a
t
)
p r
i n
t
( C )
Вывод:
[[ 1.
2.
3.]
[ 4.
5.
6.]]
Можно создать массив из диапазона:

5.1. Создание и индексация массивов
115
f r
o m
numpy i
m p
o r
t
*
L =
r a
n g
e
(5)
A = array ( L )
p r
i n
t
( A )
Вывод:
[0 1 2 3 4]
Отсюда видно, что в первом случае массив состоит из действительных чисел,
так как при определении часть его значений задана в виде десятичных дробей. В
numpy есть несколько действительнозначных типов, базовый тип соответствует действительным числам Python и называется float64. Второй массив состоит из целых чисел, потому что создан из диапазона range, в который входят толь- ко целые числа. На 64-битных операционных системах элементы такого списка будут автоматически приведены к целому типу int64, на 32-битных — к типу int32
В numpy есть функция arange, позволяющая сразу создать массив-диапазон,
причём можно использовать дробный шаг. Вот программа, рассчитывающая зна- чения синуса на одном периоде с шагом π/6:
f r
o m
numpy i
m p
o r
t
*
a1 = arange (0 , 2* pi , pi /6)
s1 = sin ( a1 )
f o
r j
i n
r a
n g
e
(
l e
n
( a1 )):
p r
i n
t
( a1 [ j ] , s1 [ j ])
А вот её вывод:
0.0 0.0 0.523598775598 0.5 1.0471975512 0.866025403784 1.57079632679 1.0 2.09439510239 0.866025403784 2.61799387799 0.5 3.14159265359 1.22464679915e-16 3.66519142919 -0.5 4.18879020479 -0.866025403784 4.71238898038 -1.0 5.23598775598 -0.866025403784 5.75958653158 -0.5
Кроме arange есть ещё функция linspace, тоже создающая массив-диапазон.
1   ...   4   5   6   7   8   9   10   11   ...   14


написать администратору сайта