Python之math模块的使用
math模块的作用
math模块实现了正常情况下原生平台C库中才有的很多专用IEEE函数,可以使用浮点值完成复杂的数学运算,包括对数和三角函数运算。
1、打印常量的示例
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))
运行效果
π: 3.141592653589793115997963468544 e: 2.718281828459045090795598298428 nan: nan inf: inf
2、测试异常值
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), ))
运行效果
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 总结: 指数变足够大时,x的平台无法再存放于一个double中,这个值就会被记录为无穷大。
3、用浮点数计算时,数据大,会抛出OverflowError异常
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)
运行效果
x = 1e+200 x*x = inf x**2 = (34, 'Result too large')
4、一个数无穷大的时候,结果为nan
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))
运行效果
x = inf isnan(x) = False y = x / x = nan y == nan = False isnan(y) = True
5、检查普通数还是特殊值
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)))
运行效果
0.00 True 1.00 True 3.14 True 2.72 True inf False nan False
6、相对比较
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))
运行效果
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 #比较失败,是因为误差小于0.1,比较不了,应该使用绝对比较
7、绝对比较
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))
运行效果
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
8、nan、inf特殊的比较
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, nan: False nan, 1.0: False inf, inf: True inf, 1.0: False
9、浮点转整数的三大方法
trunc() : 截取小数点整数部分,不做四舍五入或其它操作
floor() : 转换为不大于本身的最小整数
ceil() : 取整数部分另外有小数则整数+1
import math HEADINGS = ('i', 'int', 'trunc', '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), ))
运行效果
i int trunc 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
10、浮点转为元组的表示(小数,整数)的示例
import math for i in range(6): print('{}/2 = {}'.format(i, math.modf(i / 2.0)))
运行效果
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)
11、返回浮点数的指数和尾数的示例(返回值:尾数和指数)
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))
运行效果
x m e ------- ------- ------- 0.10 0.80 -3 0.50 0.50 0 4.00 0.50 3 使用的公式:x = m * 2**e 如 x=4.00 0.5 * 2 ** 3
12、根据尾数和指数求浮点数的示例
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))
运行效果
m e x
------- ------- -------
0.80 -3 0.10
0.50 0 0.50
0.50 3 4.00
13、求绝对值
import math print(math.fabs(-1.1)) print(math.fabs(-0.0)) print(math.fabs(0.0)) print(math.fabs(1.1))
运行效果
1.1 0.0 0.0 1.1
14、使用copysign来确认一个正确值进行比较
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, ))
运行效果
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
15、浮点数求和
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)))
运行效果
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
16、求阶乘,并且处理整数类型,小数则的异常
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))
运行效果
0 1
1 1
2 2
3 6
4 24
5 120
Error computing factorial(6.1): factorial() only accepts integral values
17、求阶乘,并且处理整数或小数类型,直到遇到负数或0则的异常
import math for i in [0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, -7]: try: print('{:2.1f} {:6.2f}'.format(i, math.gamma(i))) except ValueError as err: print('Error computing gamma({}): {}'.format(i, err))
运行效果
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 Error computing gamma(-7): math domain error
18、比gamma运算精度更准确的示例
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))
运行效果
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
19、处理浮点数的取模示例
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), ))
运行效果
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
20、取两个数之间的最大公约数
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))
运行效果
2
10
25
1
0
21、幂运算
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)))
运行效果
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
22、求平方根
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)
运行效果
3.0
1.7320508075688772
Cannot compute sqrt(-1): math domain error
23、对数,自定义底数,没有指定底数默认为e
import math print(math.log(8)) print(math.log(8, 2)) print(math.log(0.5, 2))
运行效果
2.0794415416798357 3.0 -1.0
24、log10的运算
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, ))
运行效果
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 *
25、log2的运算
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, ))
运行效果
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
26、对于非常接近于0的x,log1p()会更为精确
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))
运行效果
x : 1e-25 1 + x : 1.0 log(1+x): 0.0 log1p(x): 1e-25
27、expm1()是log1p()的逆运算,会计算e**x-1
import math x = 0.0000000000000000000000001 print(x) print(math.exp(x) - 1) print(math.expm1(x))
运行效果
1e-25
0.0
1e-25
28、exp()会计算指数函数(e**x)
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)))
运行效果
7.38905609893064951876 7.38905609893064951876 7.38905609893065040694
29、度转为弧度
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, ))
运行效果
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
30、弧度转为度
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, ))
运行效果
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
31、角
正弦sinA=对边/斜边 余弦cosA=邻边/斜边 正切tanA=对边/邻边
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))
运行效果
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
32、给定一个点计算斜边的长度
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))
运行效果
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
33、查看两点之间的距离
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, ))
运行效果
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
34、反三角函数的运算
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()
运行效果
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
35、双曲函数
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), ))
运行效果
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
36、高斯误差函数
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)))
运行效果
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
37、补余差函数
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)))
运行效果
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