Простой Python — страница 51 из 66

В последние годы в основном из-за ПО, показанного в этом приложении, Python стал очень популярен среди ученых. Если вы и сами ученый или студент, то, возможно, пользовались инструментами вроде MatLab и R или традиционными языками вроде Java, C или C++. В этом приложении вы увидите, что Python стал отличной платформой для научного анализа и публикации результатов.

Математика и статистика в стандартной библиотеке

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

Математические функции

Python имеет множество математических функций в стандартной библиотеке math (https://docs.python.org/3/library/math.html). Просто введите import math, чтобы получить к ним доступ из своих программ.

Она содержит такие константы, как pi и e:

>>> import math

>>> math.pi

>>> 3.141592653589793

>>> math.e

2.718281828459045

В основном код состоит из функций, поэтому рассмотрим наиболее полезные из них.

Функция fabs() возвращает абсолютное значение своего аргумента:

>>> math.fabs(98.6)

98.6

>>> math.fabs(-271.1)

271.1

Получаем округление вниз (floor()) и вверх (ceil()) некоторого числа:

>>> math.floor(98.6)

98

>>> math.floor(-271.1)

-272

>>> math.ceil(98.6)

99

>>> math.ceil(-271.1)

-271

Высчитываем факториал (в математике это выглядит как n!) с помощью функции factorial():

>>> math.factorial(0)

1

>>> math.factorial(1)

1

>>> math.factorial(2)

2

>>> math.factorial(3)

6

>>> math.factorial(10)

3628800

Получаем натуральный логарифм аргумента с помощью функции log():

>>> math.log(1.0)

0.0

>>> math.log(math.e)

1.0

Если вы хотите задать другое основание логарифма, передайте его как второй аргумент:

>>> math.log(8, 2)

3.0

Функция pow() возвращает противоположный результат, возводя число в степень:

>>> math.pow(2, 3)

8.0

Python имеет также встроенный оператор экспоненты **, делающий то же самое, но он не преобразует автоматически результат к числу с плавающей точкой, если основание и степень были целыми числами:

>>> 2**3

8

>>> 2.0**3

8.0

Получаем квадратный корень с помощью функции sqrt():

>>> math.sqrt(100.0)

10.0

Не пытайтесь обмануть эту функцию, она уже все это видела:

>>> math.sqrt(-100.0)

Traceback (most recent call last):

··File "", line 1, in 

ValueError: math domain error

Здесь имеются также обычные тригонометрические функции, я просто приведу их названия: sin(), cos(), tan(), asin(), acos(), atan() и atan2(). Если вы помните теорему Пифагора (или хотя бы можете произнести ее название быстро три раза, не начав плеваться), библиотека math предоставит вам также функцию hypot(), которая рассчитывает гипотенузу на основании длины двух катетов:

>>> x = 3.0

>>> y = 4.0

>>> math.hypot(x, y)

5.0

Если вы не доверяете таким функциям, можете сделать все самостоятельно:

>>> math.sqrt(x*x + y*y)

5.0

>>> math.sqrt(x**2 + y**2)

5.0

Последний набор функций преобразует угловые координаты:

>>> math.radians(180.0)

3.141592653589793

>>> math.degrees(math.pi)

180.0

Работа с комплексными числами

Комплексные числа полностью поддерживаются основой языка Python в традиционной нотации с мнимой и действительной частями:

>>> # действительное число

… 5

5

>>> # мнимое число

… 8j

8j

>>> # мнимое число

… 3 + 2j

(3+2j)

Поскольку мнимое число i (в Python оно записывается как 1j) определено как квадратный корень из –1, мы можем выполнить следующее:

>>> 1j * 1j

(-1+0j)

>>> (7 + 1j) * 1j

(-1+7j)

Некоторые математические функции для комплексных чисел содержатся в стандартном модуле cmath.

Рассчитываем точное значение чисел с плавающей точкой с помощью decimal

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

>>> x = 10.0 / 3.0

>>> x

3.3333333333333335

Эй, что это за пятерка в конце? На ее месте должна быть тройка. С помощью модуля decimal (http://docs.python.org/3/library/decimal.html) вы можете записывать числа с желаемым уровнем точности. Это особенно важно для расчетов денежных сумм. Сумма в валюте Соединенных Штатов не может быть меньше 1 цента (сотая часть доллара), поэтому, если мы подсчитываем количество долларов и центов, нам нужно считать все до копеечки. Если мы попробуем представить доллары и центы как значения с плавающей точкой вроде 19,99 или 0,06, то потеряем некоторую часть точности в последних битах еще до начала вычислений. Как с этим справиться? Легко. Нам нужно использовать модуль decimal:

>>> from decimal import Decimal

>>> price = Decimal('19.99')

>>> tax = Decimal('0.06')

>>> total = price + (price * tax)

>>> total

Decimal('21.1894')

Мы записали цену и налог как строковые значения, чтобы сохранить их точность. При вычислении переменной total мы обработали все значащие части цента, но хотим получить ближайшее целое значение цента:

>>> penny = Decimal('0.01')

>>> total.quantize(penny)

Decimal('21.19')

Такие же результаты можно получить с помощью старых добрых чисел с плавающей точкой и округлений, но не всегда. Вы можете умножить сумму на 100 и использовать при подсчетах количество центов, но и при таком подходе можете пострадать. Этот вопрос обсуждается на сайте www.itmaybeahack.com.

Выполняем вычисления для рациональных чисел с помощью модуля fractions

Вы можете представлять числа как числитель, разделенный на знаменатель, с помощью модуля стандартной библиотеки fractions (http://docs.python.org/3/library/fractions.html). Рассмотрим пример простой операции умножения 1/3 на 2/3:

>>> from fractions import Fraction

>>> Fraction(1,··3) * Fraction(2, 3)

Fraction(2, 9)

Аргументы с плавающей точкой могут быть неточными, поэтому вы можете использовать модуль Decimal вместе с модулем Fraction:

>>> Fraction(1.0/3.0)

Fraction(6004799503160661, 18014398509481984)

>>> Fraction(Decimal('1.0')/Decimal('3.0'))

Fraction(3333333333333333333333333333, 10000000000000000000000000000)

Получим наибольший общий делитель для двух чисел с помощью функции gcd:

>>> import fractions

>>> fractions.gcd(24, 16)

8

Используем Packed Sequences с помощью array

В Python список больше похож на связанный список, а не на массив. Если вы хотите получить одномерную последовательность элементов одинакового типа, применяйте тип array (http://docs.python.org/3/library/array.html). Переменные этого типа используют меньше места и поддерживают многие методы работы со списками. Создайте массив с помощью команды вида array (код типа, инициализатор). Код типа указывает на тип данных (вроде int или float), и опциональный инициализатор содержит исходные значения, которые можно передать как список, строку или итерируемое значение.

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

Обработка простой статистики с помощью модуля statistics

Начиная с версии Python 3.4, statistics является стандартным модулем (http://docs.python.org/3.4/library/statistics.html). Он содержит традиционные функции: среднее, медиану, моду, стандартное отклонение, распределение и т. д. Входными аргументами являются последовательности (списки или кортежи) или итераторы любого числового типа данных: int, float, decimal и fraction. Одна из функций, mode, также принимает в качестве аргументов строки. Для Python существует множество других статистических функций, располагающихся в пакетах SciPy и Pandas, которые мы рассмотрим далее в этом приложении.

Перемножение матриц

Начиная с Python 3.5, вы увидите символ @, который делает необычные вещи. Он все еще может использоваться для декораторов, но его также можно будет применять для перемножения матриц (http://legacy.python.org/dev/peps/pep-0465/). Однако до появления этой возможности вам следует воспользоваться NumPy.

Python для науки