python中math库最大值_Python标准库教程——math模块

写在前面

这是一篇通过例子学习Python标准库math的教程。math库提供了许多便捷的函数,能够计算常规数学运算、三角函数、双曲函数和部分特殊函数。本文翻译自 Doug Hellmann 的 PyMOTW-3项目的math模块。原文链接。

本文使用cc-by-nc-sa 4.0协议共享。

math — 数学函数

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

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

特殊常量

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

equation?tex=%5Cpi (pi),e,nan (不是数字),和

equation?tex=%7B%5Cinfty%7D

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

equation?tex=%7B%5Cpi%7D 和 e 的精度仅受平台浮点C语言库限制。

$ python3 math_constants.py

π: 3.141592653589793115997963468544

e: 2.718281828459045090795598298428

nan: nan

inf: inf

测试异常值

浮点数计算会产生两类异常值。第一类是inf(

equation?tex=%7B%5Cinfty%7D ),当用于保存浮点数的双精度值从绝对值较大的数溢出时出现。

# 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()检查常规数与特殊值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) <= 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

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

正负号

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值