Рубрики
Без рубрики

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

Автор оригинала: Doug Hellmann.

Цель:

Предоставляет функции для специализированных математических операций.

Модуль math реализует многие из функций IEEE, которые обычно можно найти в библиотеках C собственной платформы для сложных математических операций с использованием значений с плавающей запятой, включая логарифмы и тригонометрические операции.

Специальные константы

Многие математические операции зависят от специальных констант. math включает значения π (пи), e, nan (не число) и бесконечность.

math_constants.py

import math

print('  π: {:.30f}'.format(math.pi))
print('  e: {:.30f}'.format(math.e))
print('nan: {:.30f}'.format(math.nan))
print('inf: {:.30f}'.format(math.inf))

Точность π и e ограничена только библиотекой C платформы с плавающей запятой.

$ python3 math_constants.py

  π: 3.141592653589793115997963468544
  e: 2.718281828459045090795598298428
nan: nan
inf: inf

Тестирование на исключительные ценности

Вычисления с плавающей точкой могут приводить к двум типам исключительных значений. Первый из них, inf (бесконечность), появляется, когда double , используемый для хранения значения с плавающей запятой, выходит за пределы значения с большим абсолютным значением.

math_isinf.py

import math

print('{:^3} {:6} {:6} {:6}'.format(
    'e', 'x', 'x**2', 'isinf'))
print('{:-^3} {:-^6} {:-^6} {:-^6}'.format(
    '', '', '', ''))

for e in range(0, 201, 20):
    x  10.0 ** e
    y  x * x
    print('{:3d} {:<6g} {:<6g} {!s:6}'.format(
        e, x, y, math.isinf(y),
    ))

Когда показатель степени в этом примере становится достаточно большим, квадрат x больше не помещается внутри double , и значение записывается как бесконечное.

$ python3 math_isinf.py

 e  x      x**2   isinf
--- ------ ------ ------
  0 1      1      False
 20 1e+20  1e+40  False
 40 1e+40  1e+80  False
 60 1e+60  1e+120 False
 80 1e+80  1e+160 False
100 1e+100 1e+200 False
120 1e+120 1e+240 False
140 1e+140 1e+280 False
160 1e+160 inf    True
180 1e+180 inf    True
200 1e+200 inf    True

Однако не все переполнения с плавающей запятой приводят к значениям inf . В частности, вычисление экспоненты со значениями с плавающей запятой вызывает ошибку OverflowError вместо сохранения результата inf .

math_overflow.py

x  10.0 ** 200

print('x    =', x)
print('x*x  =', x * x)
print('x**2 =', end' ')
try:
    print(x ** 2)
except OverflowError as err:
    print(err)

Это несоответствие вызвано различием в реализации библиотеки, используемой C Python.

$ python3 math_overflow.py

x    = 1e+200
x*x  = inf
x**2 = (34, 'Result too large')

Операции деления с использованием бесконечных значений не определены. Результатом деления числа на бесконечность является nan (не число).

math_isnan.py

import math

x  (10.0 ** 200) * (10.0 ** 200)
y  x / x

print('x =', x)
print('isnan(x) =', math.isnan(x))
print('y = x / x =', x / x)
print('y, y  float('nan'))
print('isnan(y) =', math.isnan(y))

nan не сравнивается как равное какому-либо значению, даже самому себе, поэтому для проверки nan используйте isnan () .

$ python3 math_isnan.py

x = inf
isnan(x) = False
y = x / x = nan
y
isnan(y) = True

Используйте isfinite () , чтобы проверить наличие обычных чисел или одного из специальных значений inf или nan .

math_isfinite.py

import math

for f in [0.0, 1.0, math.pi, math.e, math.inf, math.nan]:
    print('{:5.2f} {!s}'.format(f, math.isfinite(f)))

isfinite () возвращает false для любого из исключительных случаев и true в противном случае.

$ python3 math_isfinite.py

 0.00 True
 1.00 True
 3.14 True
 2.72 True
  inf False
  nan False

Сравнение

Сравнение значений с плавающей запятой может быть подвержено ошибкам, так как каждый шаг вычисления может приводить к ошибкам из-за числового представления. Функция isclose () использует стабильный алгоритм, чтобы минимизировать эти ошибки и обеспечить способ как относительных, так и абсолютных сравнений. Используемая формула эквивалентна

abs(a-b)

По умолчанию isclose () использует относительное сравнение с допуском, установленным на 1e-09 , что означает, что разница между значениями должна быть меньше или равна 1e. -09 раз больше абсолютного значения между a и b . Передача аргумента ключевого слова rel_tol в isclose () изменяет допуск. В этом примере значения должны находиться в пределах 10% друг от друга.

math_isclose.py

import math

INPUTS  [
    (1000, 900, 0.1),
    (100, 90, 0.1),
    (10, 9, 0.1),
    (1, 0.9, 0.1),
    (0.1, 0.09, 0.1),
]

print('{:^8} {:^8} {:^8} {:^8} {:^8} {:^8}'.format(
    'a', 'b', 'rel_tol', 'abs(a-b)', 'tolerance', 'close')
)
print('{:-^8} {:-^8} {:-^8} {:-^8} {:-^8} {:-^8}'.format(
    '-', '-', '-', '-', '-', '-'),
)

fmt  '{:8.2f} {:8.2f} {:8.2f} {:8.2f} {:8.2f} {!s:>8}'

for a, b, rel_tol in INPUTS:
    close  math.isclose(a, b, rel_tolrel_tol)
    tolerance  rel_tol * max(abs(a), abs(b))
    abs_diff  abs(a - b)
    print(fmt.format(a, b, rel_tol, abs_diff, tolerance, close))

Сравнение между 0,1 и 0,09 не удается из-за ошибки, представляющей 0,1 .

$ python3 math_isclose.py

   a        b     rel_tol  abs(a-b) tolerance  close
-------- -------- -------- -------- -------- --------
 1000.00   900.00     0.10   100.00   100.00     True
  100.00    90.00     0.10    10.00    10.00     True
   10.00     9.00     0.10     1.00     1.00     True
    1.00     0.90     0.10     0.10     0.10     True
    0.10     0.09     0.10     0.01     0.01    False

Чтобы использовать фиксированный или «абсолютный» допуск, передайте abs_tol вместо rel_tol .

math_isclose_abs_tol.py

import math

INPUTS  [
    (1.0, 1.0 + 1e-07, 1e-08),
    (1.0, 1.0 + 1e-08, 1e-08),
    (1.0, 1.0 + 1e-09, 1e-08),
]

print('{:^8} {:^11} {:^8} {:^10} {:^8}'.format(
    'a', 'b', 'abs_tol', 'abs(a-b)', 'close')
)
print('{:-^8} {:-^11} {:-^8} {:-^10} {:-^8}'.format(
    '-', '-', '-', '-', '-'),
)

for a, b, abs_tol in INPUTS:
    close  math.isclose(a, b, abs_tolabs_tol)
    abs_diff  abs(a - b)
    print('{:8.2f} {:11} {:8} {:0.9f} {!s:>8}'.format(
        a, b, abs_tol, abs_diff, close))

Для абсолютного допуска разница между входными значениями должна быть меньше заданного допуска.

$ python3 math_isclose_abs_tol.py

   a          b      abs_tol   abs(a-b)   close
-------- ----------- -------- ---------- --------
    1.00   1.0000001    1e-08 0.000000100    False
    1.00  1.00000001    1e-08 0.000000010     True
    1.00 1.000000001    1e-08 0.000000001     True

nan и inf – особые случаи.

math_isclose_inf.py

import math

print('nan, nan:', math.isclose(math.nan, math.nan))
print('nan, 1.0:', math.isclose(math.nan, 1.0))
print('inf, inf:', math.isclose(math.inf, math.inf))
print('inf, 1.0:', math.isclose(math.inf, 1.0))

nan никогда не приближается к другому значению, включая его самого. inf находится близко к самому себе.

$ python3 math_isclose_inf.py

nan, nan: False
nan, 1.0: False
inf, inf: True
inf, 1.0: False

Преобразование значений с плавающей запятой в целые числа

Модуль math включает три функции для преобразования значений с плавающей запятой в целые числа. Каждый из них использует свой подход и будет полезен в разных обстоятельствах.

Самым простым является trunc () , который обрезает цифры, следующие за десятичной дробью, оставляя только значащие цифры, составляющие целую числовую часть значения. floor () преобразует свои входные данные в наибольшее предшествующее целое число, а ceil () (потолок) создает наибольшее целое число, следующее последовательно после входного значения.

math_integers.py

import math

HEADINGS  ('i', 'int', 'trunk', 'floor', 'ceil')
print('{:^5} {:^5} {:^5} {:^5} {:^5}'.format(*HEADINGS))
print('{:-^5} {:-^5} {:-^5} {:-^5} {:-^5}'.format(
    '', '', '', '', '',
))

fmt  '{:5.1f} {:5.1f} {:5.1f} {:5.1f} {:5.1f}'

TEST_VALUES  [
    -1.5,
    -0.8,
    -0.5,
    -0.2,
    0,
    0.2,
    0.5,
    0.8,
    1,
]

for i in TEST_VALUES:
    print(fmt.format(
        i,
        int(i),
        math.trunc(i),
        math.floor(i),
        math.ceil(i),
    ))

trunc () эквивалентен прямому преобразованию в int .

$ python3 math_integers.py

  i    int  trunk floor ceil
----- ----- ----- ----- -----
 -1.5  -1.0  -1.0  -2.0  -1.0
 -0.8   0.0   0.0  -1.0   0.0
 -0.5   0.0   0.0  -1.0   0.0
 -0.2   0.0   0.0  -1.0   0.0
  0.0   0.0   0.0   0.0   0.0
  0.2   0.0   0.0   0.0   1.0
  0.5   0.0   0.0   0.0   1.0
  0.8   0.0   0.0   0.0   1.0
  1.0   1.0   1.0   1.0   1.0

Альтернативные представления значений с плавающей запятой

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

math_modf.py

import math

for i in range(6):
    print('{}/2 = {}'.format(i, math.modf(i / 2.0)))

Оба числа в возвращаемом значении являются числами с плавающей запятой.

$ python3 math_modf.py

0/2 = (0.0, 0.0)
1/2 = (0.5, 0.0)
2/2 = (0.0, 1.0)
3/2 = (0.5, 1.0)
4/2 = (0.0, 2.0)
5/2 = (0.5, 2.0)

frexp () возвращает мантиссу и показатель степени числа с плавающей запятой и может использоваться для создания более переносимого представления значения.

math_frexp.py

import math

print('{:^7} {:^7} {:^7}'.format('x', 'm', 'e'))
print('{:-^7} {:-^7} {:-^7}'.format('', '', ''))

for x in [0.1, 0.5, 4.0]:
    m, e  math.frexp(x)
    print('{:7.2f} {:7.2f} {:7d}'.format(x, m, e))

frexp () использует формулу x m * 2 ** e и возвращает значения m и e .

$ python3 math_frexp.py

   x       m       e
------- ------- -------
   0.10    0.80      -3
   0.50    0.50       0
   4.00    0.50       3

ldexp () является обратным к frexp () .

math_ldexp.py

import math

print('{:^7} {:^7} {:^7}'.format('m', 'e', 'x'))
print('{:-^7} {:-^7} {:-^7}'.format('', '', ''))

INPUTS  [
    (0.8, -3),
    (0.5, 0),
    (0.5, 3),
]

for m, e in INPUTS:
    x  math.ldexp(m, e)
    print('{:7.2f} {:7d} {:7.2f}'.format(m, e, x))

Используя ту же формулу, что и frexp () , ldexp () принимает значения мантиссы и экспоненты в качестве аргументов и возвращает число с плавающей запятой.

$ python3 math_ldexp.py

   m       e       x
------- ------- -------
   0.80      -3    0.10
   0.50       0    0.50
   0.50       3    4.00

Положительные и отрицательные признаки

Абсолютное значение числа – это его значение без знака. Используйте fabs () для вычисления абсолютного значения числа с плавающей запятой.

math_fabs.py

import math

print(math.fabs(-1.1))
print(math.fabs(-0.0))
print(math.fabs(0.0))
print(math.fabs(1.1))

На практике абсолютное значение float представляется как положительное значение.

$ python3 math_fabs.py

1.1
0.0
0.0
1.1

Чтобы определить знак значения, либо чтобы присвоить набору значений одинаковый знак, либо для сравнения двух значений, используйте copysign () , чтобы установить знак заведомо правильного значения.

math_copysign.py

import math

HEADINGS  ('f', 's', '< 0', '> 0',  0, f  0,
    ))

Необходима дополнительная функция, такая как copysign () , поскольку прямое сравнение nan и -nan с другими значениями не работает.

$ python3 math_copysign.py

  f     s    < 0   > 0   = 0
----- ----- ----- ----- -----
 -1.0    -1 True  False False
  0.0     1 False False True
  1.0     1 False True  False
 -inf    -1 True  False False
  inf     1 False True  False
  nan    -1 False False False
  nan     1 False False False

Часто используемые расчеты

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

math_fsum.py

import math

values  [0.1] * 10

print('Input values:', values)

print('sum()       : {:.20f}'.format(sum(values)))

s  0.0
for i in values:
    s  i
print('for-loop    : {:.20f}'.format(s))

print('math.fsum() : {:.20f}'.format(math.fsum(values)))

Для последовательности из десяти значений, каждое из которых равно 0,1 , ожидаемое значение суммы последовательности будет 1,0 . Поскольку 0.1 не может быть точно представлен как значение с плавающей запятой, однако, в сумму вносятся ошибки, если она не вычисляется с помощью fsum () .

$ python3 math_fsum.py

Input values: [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
sum()       : 0.99999999999999988898
for-loop    : 0.99999999999999988898
math.fsum() : 1.00000000000000000000

factorial () обычно используется для вычисления количества перестановок и комбинаций ряда объектов. Факториал положительного целого числа n , выраженный n! , рекурсивно определяется как (n-1)! * n и останавливается на 0! 1 .

math_factorial.py

import math

for i in [0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.1]:
    try:
        print('{:2.0f} {:6.0f}'.format(i, math.factorial(i)))
    except ValueError as err:
        print('Error computing factorial({}): {}'.format(i, err))

factorial () работает только с целыми числами, но принимает аргументы float , если они могут быть преобразованы в целое число без потери значения.

$ python3 math_factorial.py

 0      1
 1      1
 2      2
 3      6
 4     24
 5    120
Error computing factorial(6.1): factorial() only accepts integral
 values

gamma () похож на factorial () , за исключением того, что он работает с действительными числами, и значение сдвигается вниз на единицу (гамма равна (n - 1) ! ).

math_gamma.py

import math

for i in [0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6]:
    try:
        print('{:2.1f} {:6.2f}'.format(i, math.gamma(i)))
    except ValueError as err:
        print('Error computing gamma({}): {}'.format(i, err))

Поскольку ноль приводит к отрицательному начальному значению, это недопустимо.

$ python3 math_gamma.py

Error computing gamma(0): math domain error
1.1   0.95
2.2   1.10
3.3   2.68
4.4  10.14
5.5  52.34
6.6 344.70

lgamma () возвращает натуральный логарифм абсолютного значения гаммы для входного значения.

math_lgamma.py

import math

for i in [0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6]:
    try:
        print('{:2.1f} {:.20f} {:.20f}'.format(
            i,
            math.lgamma(i),
            math.log(math.gamma(i)),
        ))
    except ValueError as err:
        print('Error computing lgamma({}): {}'.format(i, err))

Использование lgamma () сохраняет большую точность, чем вычисление логарифма отдельно с использованием результатов gamma () .

$ python3 math_lgamma.py

Error computing lgamma(0): math domain error
1.1 -0.04987244125984036103 -0.04987244125983997245
2.2 0.09694746679063825923 0.09694746679063866168
3.3 0.98709857789473387513 0.98709857789473409717
4.4 2.31610349142485727469 2.31610349142485727469
5.5 3.95781396761871651080 3.95781396761871606671
6.6 5.84268005527463252236 5.84268005527463252236

Оператор по модулю (% ) вычисляет остаток от выражения деления (т. Е. 5% 2 1 ). Встроенный в язык оператор хорошо работает с целыми числами, но, как и многие другие операции с плавающей запятой, промежуточные вычисления вызывают проблемы с представлением, которые приводят к потере данных. fmod () обеспечивает более точную реализацию значений с плавающей запятой.

math_fmod.py

import math

print('{:^4} {:^4} {:^5} {:^5}'.format(
    'x', 'y', '%', 'fmod'))
print('{:-^4} {:-^4} {:-^5} {:-^5}'.format(
    '-', '-', '-', '-'))

INPUTS  [
    (5, 2),
    (5, -2),
    (-5, 2),
]

for x, y in INPUTS:
    print('{:4.1f} {:4.1f} {:5.2f} {:5.2f}'.format(
        x,
        y,
        x % y,
        math.fmod(x, y),
    ))

Потенциально более частым источником путаницы является тот факт, что алгоритм, используемый fmod () для вычисления по модулю, также отличается от того, который используется % , поэтому знак результата отличается.

$ python3 math_fmod.py

 x    y     %   fmod
---- ---- ----- -----
 5.0  2.0  1.00  1.00
 5.0 -2.0 -1.00  1.00
-5.0  2.0  1.00 -1.00

Используйте gcd () , чтобы найти наибольшее целое число, которое может делиться на два целых числа, наибольший общий делитель.

math_gcd.py

import math

print(math.gcd(10, 8))
print(math.gcd(10, 0))
print(math.gcd(50, 225))
print(math.gcd(11, 9))
print(math.gcd(0, 0))

Если оба значения равны 0 , результат будет 0 .

$ python3 math_gcd.py

2
10
25
1
0

Показатели и логарифмы

Кривые экспоненциального роста появляются в экономике, физике и других науках. Python имеет встроенный оператор возведения в степень (“ ** “), но pow () может быть полезен, когда вызываемая функция необходима в качестве аргумента для другой функции.

math_pow.py

import math

INPUTS  [
    # Typical uses
    (2, 3),
    (2.1, 3.2),

    # Always 1
    (1.0, 5),
    (2.0, 0),

    # Not-a-number
    (2, float('nan')),

    # Roots
    (9.0, 0.5),
    (27.0, 1.0 / 3),
]

for x, y in INPUTS:
    print('{:5.1f} ** {:5.3f} = {:6.3f}'.format(
        x, y, math.pow(x, y)))

Повышение 1 до любой степени всегда возвращает 1.0 , как и повышение любого значения до степени 0.0 . Большинство операций с нечисловым значением nan возвращают nan . Если показатель степени меньше 1 , pow () вычисляет корень.

$ python3 math_pow.py

  2.0 ** 3.000 =  8.000
  2.1 ** 3.200 = 10.742
  1.0 ** 5.000 =  1.000
  2.0 ** 0.000 =  1.000
  2.0 **   nan =    nan
  9.0 ** 0.500 =  3.000
 27.0 ** 0.333 =  3.000

Поскольку квадратные корни (показатель степени от 1/2 ) используются так часто, для их вычисления есть отдельная функция.

math_sqrt.py

import math

print(math.sqrt(9.0))
print(math.sqrt(3))
try:
    print(math.sqrt(-1))
except ValueError as err:
    print('Cannot compute sqrt(-1):', err)

Для вычисления квадратных корней из отрицательных чисел требуются комплексные числа , которые не обрабатываются math . Любая попытка вычислить квадратный корень из отрицательного значения приводит к ValueError .

$ python3 math_sqrt.py

3.0
1.7320508075688772
Cannot compute sqrt(-1): math domain error

Функция логарифма находит y , где x b ** y . По умолчанию log () вычисляет натуральный логарифм (с основанием e ). Если указан второй аргумент, это значение используется как базовое.

math_log.py

import math

print(math.log(8))
print(math.log(8, 2))
print(math.log(0.5, 2))

Логарифмы, в которых x меньше единицы, дают отрицательный результат.

$ python3 math_log.py

2.0794415416798357
3.0
-1.0

Существует три варианта log () . Учитывая ошибки представления с плавающей запятой и округления, вычисленное значение, полученное с помощью log (x, b) , имеет ограниченную точность, особенно для некоторых оснований. log10 () вычисляет log (x, 10) , используя более точный алгоритм, чем log () .

math_log10.py

import math

print('{:2} {:^12} {:^10} {:^20} {:8}'.format(
    'i', 'x', 'accurate', 'inaccurate', 'mismatch',
))
print('{:-^2} {:-^12} {:-^10} {:-^20} {:-^8}'.format(
    '', '', '', '', '',
))

for i in range(0, 10):
    x  math.pow(10, i)
    accurate  math.log10(x)
    inaccurate  math.log(x, 10)
    match  '' if int(inaccurate)  i else '*'
    print('{:2d} {:12.1f} {:10.8f} {:20.18f} {:^5}'.format(
        i, x, accurate, inaccurate, match,
    ))

Строки в выводе с завершающим * выделяют неточные значения.

$ python3 math_log10.py

i       x        accurate       inaccurate      mismatch
-- ------------ ---------- -------------------- --------
 0          1.0 0.00000000 0.000000000000000000
 1         10.0 1.00000000 1.000000000000000000
 2        100.0 2.00000000 2.000000000000000000
 3       1000.0 3.00000000 2.999999999999999556   *
 4      10000.0 4.00000000 4.000000000000000000
 5     100000.0 5.00000000 5.000000000000000000
 6    1000000.0 6.00000000 5.999999999999999112   *
 7   10000000.0 7.00000000 7.000000000000000000
 8  100000000.0 8.00000000 8.000000000000000000
 9 1000000000.0 9.00000000 8.999999999999998224   *

Подобно log10 () , log2 () вычисляет эквивалент math.log (x, 2) .

math_log2.py

import math

print('{:>2} {:^5} {:^5}'.format(
    'i', 'x', 'log2',
))
print('{:-^2} {:-^5} {:-^5}'.format(
    '', '', '',
))

for i in range(0, 10):
    x  math.pow(2, i)
    result  math.log2(x)
    print('{:2d} {:5.1f} {:5.1f}'.format(
        i, x, result,
    ))

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

$ python3 math_log2.py

 i   x   log2
-- ----- -----
 0   1.0   0.0
 1   2.0   1.0
 2   4.0   2.0
 3   8.0   3.0
 4  16.0   4.0
 5  32.0   5.0
 6  64.0   6.0
 7 128.0   7.0
 8 256.0   8.0
 9 512.0   9.0

log1p () вычисляет ряд Ньютона-Меркатора (натуральный логарифм от 1 + x ).

math_log1p.py

import math

x  0.0000000000000000000000001
print('x       :', x)
print('1 + x   :', 1 + x)
print('log(1+x):', math.log(1 + x))
print('log1p(x):', math.log1p(x))

log1p () более точен для значений x , очень близких к нулю, поскольку в нем используется алгоритм, который компенсирует ошибки округления при начальном добавлении.

$ python3 math_log1p.py

x       : 1e-25
1 + x   : 1.0
log(1+x): 0.0
log1p(x): 1e-25

exp () вычисляет экспоненциальную функцию ( e ** x ).

math_exp.py

import math

x  2

fmt  '{:.20f}'
print(fmt.format(math.e ** 2))
print(fmt.format(math.pow(math.e, 2)))
print(fmt.format(math.exp(2)))

Как и в случае с другими функциями специального случая, он использует алгоритм, который дает более точные результаты, чем эквивалент общего назначения math.pow (math.e, x) .

$ python3 math_exp.py

7.38905609893064951876
7.38905609893064951876
7.38905609893065040694

expm1 () является обратным к log1p () и вычисляет e ** x - 1 .

math_expm1.py

import math

x  0.0000000000000000000000001

print(x)
print(math.exp(x) - 1)
print(math.expm1(x))

Маленькие значения x теряют точность, когда вычитание выполняется отдельно, как в случае с log1p () .

$ python3 math_expm1.py

1e-25
0.0
1e-25

Углы

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

Окружность рассчитывается как 2πr , поэтому существует связь между радианами и π, значением, которое часто появляется в тригонометрических вычислениях. Это соотношение приводит к тому, что радианы используются в тригонометрии и исчислении, поскольку они приводят к более компактным формулам.

Чтобы преобразовать градусы в радианы, используйте радианы () .

math_radians.py

import math

print('{:^7} {:^7} {:^7}'.format(
    'Degrees', 'Radians', 'Expected'))
print('{:-^7} {:-^7} {:-^7}'.format(
    '', '', ''))

INPUTS  [
    (0, 0),
    (30, math.pi / 6),
    (45, math.pi / 4),
    (60, math.pi / 3),
    (90, math.pi / 2),
    (180, math.pi),
    (270, 3 / 2.0 * math.pi),
    (360, 2 * math.pi),
]

for deg, expected in INPUTS:
    print('{:7d} {:7.2f} {:7.2f}'.format(
        deg,
        math.radians(deg),
        expected,
    ))

Формула преобразования: rad deg * π/180 .

$ python3 math_radians.py

Degrees Radians Expected
------- ------- -------
      0    0.00    0.00
     30    0.52    0.52
     45    0.79    0.79
     60    1.05    1.05
     90    1.57    1.57
    180    3.14    3.14
    270    4.71    4.71
    360    6.28    6.28

Чтобы преобразовать радианы в градусы, используйте градусы () .

math_degrees.py

import math

INPUTS  [
    (0, 0),
    (math.pi / 6, 30),
    (math.pi / 4, 45),
    (math.pi / 3, 60),
    (math.pi / 2, 90),
    (math.pi, 180),
    (3 * math.pi / 2, 270),
    (2 * math.pi, 360),
]

print('{:^8} {:^8} {:^8}'.format(
    'Radians', 'Degrees', 'Expected'))
print('{:-^8} {:-^8} {:-^8}'.format('', '', ''))
for rad, expected in INPUTS:
    print('{:8.2f} {:8.2f} {:8.2f}'.format(
        rad,
        math.degrees(rad),
        expected,
    ))

Формула: град. Рад * 180/π .

$ python3 math_degrees.py

Radians  Degrees  Expected
-------- -------- --------
    0.00     0.00     0.00
    0.52    30.00    30.00
    0.79    45.00    45.00
    1.05    60.00    60.00
    1.57    90.00    90.00
    3.14   180.00   180.00
    4.71   270.00   270.00
    6.28   360.00   360.00

Тригонометрия

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

Если задан угол в прямоугольном треугольнике, синус – это отношение длины стороны, противоположной углу, к гипотенузе ( sin A противоположный/гипотенуза ). косинус – это отношение длины смежной стороны к гипотенузе ( cos A прилегающей/гипотенуза ). А касательная – это отношение противоположной стороны к прилегающей ( tan A противоположная/смежная ).

math_trig.py

import math

print('{:^7} {:^7} {:^7} {:^7} {:^7}'.format(
    'Degrees', 'Radians', 'Sine', 'Cosine', 'Tangent'))
print('{:-^7} {:-^7} {:-^7} {:-^7} {:-^7}'.format(
    '-', '-', '-', '-', '-'))

fmt  '{:7.2f} {:7.2f} {:7.2f} {:7.2f} {:7.2f}'

for deg in range(0, 361, 30):
    rad  math.radians(deg)
    if deg in (90, 270):
        t  float('inf')
    else:
        t  math.tan(rad)
    print(fmt.format(deg, rad, math.sin(rad), math.cos(rad), t))

Тангенс также можно определить как отношение синуса угла к его косинусу, и поскольку косинус равен 0 для π/2 и 3π/2 радиан, касательная бесконечна.

$ python3 math_trig.py

Degrees Radians  Sine   Cosine  Tangent
------- ------- ------- ------- -------
   0.00    0.00    0.00    1.00    0.00
  30.00    0.52    0.50    0.87    0.58
  60.00    1.05    0.87    0.50    1.73
  90.00    1.57    1.00    0.00     inf
 120.00    2.09    0.87   -0.50   -1.73
 150.00    2.62    0.50   -0.87   -0.58
 180.00    3.14    0.00   -1.00   -0.00
 210.00    3.67   -0.50   -0.87    0.58
 240.00    4.19   -0.87   -0.50    1.73
 270.00    4.71   -1.00   -0.00     inf
 300.00    5.24   -0.87    0.50   -1.73
 330.00    5.76   -0.50    0.87   -0.58
 360.00    6.28   -0.00    1.00   -0.00

Для точки (x, y) длина гипотенузы треугольника между точками [(0, 0), ( x , 0), ( x , y )] равно (x ** 2 + y ** 2) ** 1/2 и может быть вычислено с помощью гипотеза () .

math_hypot.py

import math

print('{:^7} {:^7} {:^10}'.format('X', 'Y', 'Hypotenuse'))
print('{:-^7} {:-^7} {:-^10}'.format('', '', ''))

POINTS  [
    # simple points
    (1, 1),
    (-1, -1),
    (math.sqrt(2), math.sqrt(2)),
    (3, 4),  # 3-4-5 triangle
    # on the circle
    (math.sqrt(2) / 2, math.sqrt(2) / 2),  # pi/4 rads
    (0.5, math.sqrt(3) / 2),  # pi/3 rads
]

for x, y in POINTS:
    h  math.hypot(x, y)
    print('{:7.2f} {:7.2f} {:7.2f}'.format(x, y, h))

Гипотенуза точек на окружности всегда равна 1.

$ python3 math_hypot.py

   X       Y    Hypotenuse
------- ------- ----------
   1.00    1.00    1.41
  -1.00   -1.00    1.41
   1.41    1.41    2.00
   3.00    4.00    5.00
   0.71    0.71    1.00
   0.50    0.87    1.00

Эту же функцию можно использовать для определения расстояния между двумя точками.

math_distance_2_points.py

import math

print('{:^8} {:^8} {:^8} {:^8} {:^8}'.format(
    'X1', 'Y1', 'X2', 'Y2', 'Distance',
))
print('{:-^8} {:-^8} {:-^8} {:-^8} {:-^8}'.format(
    '', '', '', '', '',
))

POINTS  [
    ((5, 5), (6, 6)),
    ((-6, -6), (-5, -5)),
    ((0, 0), (3, 4)),  # 3-4-5 triangle
    ((-1, -1), (2, 3)),  # 3-4-5 triangle
]

for (x1, y1), (x2, y2) in POINTS:
    x  x1 - x2
    y  y1 - y2
    h  math.hypot(x, y)
    print('{:8.2f} {:8.2f} {:8.2f} {:8.2f} {:8.2f}'.format(
        x1, y1, x2, y2, h,
    ))

Используйте разницу в значениях x и y , чтобы переместить одну конечную точку в исходную точку, а затем передайте результаты в hypot () .

$ python3 math_distance_2_points.py

   X1       Y1       X2       Y2    Distance
-------- -------- -------- -------- --------
    5.00     5.00     6.00     6.00     1.41
   -6.00    -6.00    -5.00    -5.00     1.41
    0.00     0.00     3.00     4.00     5.00
   -1.00    -1.00     2.00     3.00     5.00

math также определяет обратные тригонометрические функции.

math_inverse_trig.py

import math

for r in [0, 0.5, 1]:
    print('arcsine({:.1f})    = {:5.2f}'.format(r, math.asin(r)))
    print('arccosine({:.1f})  = {:5.2f}'.format(r, math.acos(r)))
    print('arctangent({:.1f}) = {:5.2f}'.format(r, math.atan(r)))
    print()

1,57 примерно равно π/2 , или 90 градусам, углу, под которым синус равен 1, а косинус равен 0.

$ python3 math_inverse_trig.py

arcsine(0.0)    =  0.00
arccosine(0.0)  =  1.57
arctangent(0.0) =  0.00

arcsine(0.5)    =  0.52
arccosine(0.5)  =  1.05
arctangent(0.5) =  0.46

arcsine(1.0)    =  1.57
arccosine(1.0)  =  0.00
arctangent(1.0) =  0.79

Гиперболические функции

Гиперболические функции появляются в линейных дифференциальных уравнениях и используются при работе с электромагнитными полями, гидродинамикой, специальной теорией относительности и другими передовыми физическими и математическими науками.

math_hyperbolic.py

import math

print('{:^6} {:^6} {:^6} {:^6}'.format(
    'X', 'sinh', 'cosh', 'tanh',
))
print('{:-^6} {:-^6} {:-^6} {:-^6}'.format('', '', '', ''))

fmt  '{:6.4f} {:6.4f} {:6.4f} {:6.4f}'

for i in range(0, 11, 2):
    x  i / 10.0
    print(fmt.format(
        x,
        math.sinh(x),
        math.cosh(x),
        math.tanh(x),
    ))

В то время как функции косинуса и синуса описывают окружность, гиперболический косинус и гиперболический синус образуют половину гиперболы.

$ python3 math_hyperbolic.py

  X     sinh   cosh   tanh
------ ------ ------ ------
0.0000 0.0000 1.0000 0.0000
0.2000 0.2013 1.0201 0.1974
0.4000 0.4108 1.0811 0.3799
0.6000 0.6367 1.1855 0.5370
0.8000 0.8881 1.3374 0.6640
1.0000 1.1752 1.5431 0.7616

Также доступны обратные гиперболические функции acosh () , asinh () и atanh () .

Специальные функции

Функция ошибки Гаусса используется в статистике.

math_erf.py

import math

print('{:^5} {:7}'.format('x', 'erf(x)'))
print('{:-^5} {:-^7}'.format('', ''))

for x in [-3, -2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1, 2, 3]:
    print('{:5.2f} {:7.4f}'.format(x, math.erf(x)))

Для функции ошибки erf (-x) -erf (x) .

$ python3 math_erf.py

  x   erf(x)
----- -------
-3.00 -1.0000
-2.00 -0.9953
-1.00 -0.8427
-0.50 -0.5205
-0.25 -0.2763
 0.00  0.0000
 0.25  0.2763
 0.50  0.5205
 1.00  0.8427
 2.00  0.9953
 3.00  1.0000

Дополнительная функция ошибок – 1 - erf (x) .

math_erfc.py

import math

print('{:^5} {:7}'.format('x', 'erfc(x)'))
print('{:-^5} {:-^7}'.format('', ''))

for x in [-3, -2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1, 2, 3]:
    print('{:5.2f} {:7.4f}'.format(x, math.erfc(x)))

Реализация erfc () позволяет избежать ошибок точности для малых значений x при вычитании из 1.

$ python3 math_erfc.py

  x   erfc(x)
----- -------
-3.00  2.0000
-2.00  1.9953
-1.00  1.8427
-0.50  1.5205
-0.25  1.2763
 0.00  1.0000
 0.25  0.7237
 0.50  0.4795
 1.00  0.1573
 2.00  0.0047
 3.00  0.0000

Смотрите также