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(
    '-', '-', '-', '-', 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值