python如何导入math库_Python标准库教程——math模块

写在前面

这是一篇通过例子学习Python标准库math的教程。math库提供了许多便捷的函数,能够计算常规数学运算、三角函数、双曲函数和部分特殊函数。


本文翻译自 Doug Hellmann 的 PyMOTW-3项目的math模块。原文链接。
本文使用cc-by-nc-sa 4.0协议共享。

math — 数学函数

目的:为特殊数学运算提供函数。

math 模块实现了许多IEEE使用浮点数进行复杂数学运算的函数,包括对数和三角函数运算,这些函数通常可以在本地C库找到。

特殊常量

许多数学运算基于特殊常量。math提供的值有,

(pi),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(

),当用于保存浮点数的双精度值从绝对值较大的数溢出时出现。
# 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的平方不再包含于双精度值,并将该值记录为无穷。

$ 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 == nan =', y == float('nan'))
print('isnan(y) =', math.isnan(y))

nan不与任何值相等,包括它本身,所以需用 isnan() 检查 nan

$ python3 math_isnan.py

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

使用isfinite()检查常规数与特殊值infnan

# 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) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

默认情况下,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_tol=rel_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.1和0.09的比较返回Flase

$ 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_tol=abs_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

naninf是特例。

# 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,并返回值me

$ 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))

正负号

数字的绝对值是不带符号的值。 使用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))

实际上,浮点数的绝对值表示为正值。

$ python3 math_fabs.py

1.1
0.0
0.0
1.1

为确定值的符号,可以赋予一组值相同的符号或比较两个值,使用copysign()设置已知有效值的符号。

# math_copysign.py

import math

HEADINGS = ('f', 's', '< 0', '> 0', '= 0')
print('{:^5} {:^5} {:^5} {:^5} {:^5}'.format(*HEADINGS))
print('{:-^5} {:-^5} {:-^5} {:-^5} {:-^5}'.format(
    '', '', '', '', '',
))

VALUES = [
    -1.0,
    0.0,
    1.0,
    float('-inf'),
    float('inf'),
    float('-nan'),
    float('nan'),
]

for f in VALUES:
    s = int(math.copysign(1, f))
    print('{:5.1f} {:5d} {!s:5} {!s:5} {!s:5}'.format(
        f, s, f < 0, f > 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()仅适用于整数,但会接受浮点参数,只要它们可以转换为整数而不会丢失值。

$ 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()相似,除了它处理的是实数且值向下移动了一位 ( gammar()等价于(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))

由于0会导致初始值为负,故不允许这样做。

$ 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()返回输入值的gamma绝对值的自然对数。

# 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

取模运算符 (%) 用来计算除法表达式的余数 (i.e., 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次方也是如此。对非数字值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

对数函数在当 x = b ** y 时找到 y 。默认情况下,log()计算自然对数(以e为底数)。如果提供第二个参数,则以该值为底数。

# math_log.py

import math

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

当x < 1时的对数结果为负。

$ python3 math_log.py

2.0794415416798357
3.0
-1.0

给定浮点数表示法和舍入误差,log(x,b)产生的计算值的准确性有限,尤其是对于某些基数而言。 log10()使用比log()更精确的算法来计算log(x,10)

# 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

角度

虽然角度制在日常生活中更常用,但在科学和数学中弧度制是衡量角度的标准单位。1弧度是由两条线在圆心相交而形成的角度,两条线的末端在圆周上相距一个半径。

圆的周长记为2πr,因此弧度和之间存在一种联系,该值在三角函数计算中经常出现。这种联系使得弧度被应用在三角学和微积分中,因为使用它们可产生更紧凑的公式。

要将度转换为弧度,请使用radians()

# 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

要将弧度转换为度,请使用degree()

# 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,
    ))

转换公式为deg = rad * 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))

tan也可以被定义为角的正弦与其余弦之比,并且由于π/ 2和3π/ 2弧度的余弦为0,所以tan是无限大的。

$ 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,可以用hypot()计算。

# 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()的实现避免了从1减去x的小数值的精度误差。

$ 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
See also
- Standard library documentation for math
- IEEE floating point arithmetic in Python – Blog post by John Cook about how special values arise and are dealt with when doing math in Python.
- SciPy – Open source libraryes for scientific and mathematical calculations in Python. - PEP 485 – “A function for testing approximate equality”

你可能感兴趣的:(python如何导入math库)