3、数字日期和时间
3.1数字的四舍五入
print(round(1.23,1))
print(round(1.27,1))
print(round(1.5,0))
print(round(2.5,0))#当一个值刚好在两个边界的中间的时候,`round()`函数返回离它最近的偶数。
print(round(3.5,0))
1.2
1.3
2.0
2.0
4.0
传给round()
函数的ndigits
参数可以是附属,这种情况下,舍入运算会作用在十位、百位、千位等上面。
数字的格式化(是小数点后保留几位小数),注意区分与四舍五入之间的差别
print(format( 1.23,'0.1f'))
print(format( 1.27,'0.1f'))
print(format( 1.5,'0.0f'))
print(format( 2.5,'0.0f'))
print(format( 3.5,'0.0f'))
1.2
1.3
2
2
4
3.2执行精确的浮点数运算
浮点数的一个普遍问题是它们并不能精确的表示十进制数。并且,即使是最简单的数学运算也会产生小的误差。
a = 4.2
b = 2.1
print(a+b)#6.300000000000001
这些错误是由底层CPU和IEEE754标准通过自己的浮点单位去执行算术时的特征,由于Python的浮点数据类型使用底层表示数据存储,因此你没办法避免这样的误差。
from decimal import Decimal
a = Decimal('4.2')
b = Decimal('2.1')
print(type(a+b))#<class 'decimal.Decimal'>
print(a+b)#6.3
decimal
模块的一个主要特征是允许你控制计算的每一方面,包括数字位数和四舍五入运算。为了这么做,你先得创建一个本地上下文并更改它的位置。
from decimal import Decimal,localcontext
a = Decimal('1.3')
b = Decimal('1.7')
print(a/b)#0.7647058823529411764705882353
with localcontext() as ctx:
ctx.prec = 3
print(a/b)#0.765
with localcontext() as ctx:
ctx.prec = 50
print(a/b)#0.76470588235294117647058823529411764705882352941176
nums = [1.23e+18,1,-1.23e+18]
print(sum(nuts))#0.0
nums = [1.23e+18,-1.23e+18,1]
print(sum(nuts))#1.0
这个错误可以利用math.fsum()
所提供的更精确的计算能力来解决
import math
nums = [1.23e+18,1,-1.23e+18]
print(math.fsum(nuts))#1.0
nums = [1.23e+18,-1.23e+18,1]
print(math.fsum(nuts))#1.0
总的来说,decimal
模块主要用在涉及到金融的领域。
3.3数字的格式化输出
你需要将数字格式化后输出,并控制数字的位数、对齐、千位分隔符和其他的细节。
格式化输出单个数字的时候,可以使用内置的 format()
函数
如果你想使用指数记法,将f改成e或者E(取决于指数输出的大小写形式)
x = 1234.56789
print(format(x,'e'))#1.234568e+03
print(format(x,'0.2E'))#1.23E+03
在很多Python代码中会看到使用%来格式化数字的
3.4二八十六进制整数
你需要转换或者输出使用二进制,八进制或十六进制表示的整数。
为了将整数转换为二进制、八进制、或十六进制的文本串,可以分别使用bin()
,oct()
,或hex()
函数:
如果不想输出0b
,0o
,0x
的前缀的话,可以使用format()
函数
x = 32
print(bin(x))#0b100000
print(format(x,'b'))#100000
print(oct(x))#0o40
print(format(x,'o'))#40
print(hex(x))#0x20
print(format(x,'x'))#20
为了将不同进制的数转换为整数,简单的使用带有进制的int()
函数即可
print(int('20',16))#32
print(int('11111',2))#31
3.5字节到大整数的打包与解包
你有一个字节字符串并想将它解压成一个整数。或者,你需要将一个大整数转换为一个字节字符串。
假设你的程序需要处理一个拥有128位长的16个元素的字节字符串。
3.6复数的数学运算
3.8分数运算
fractions
模块可以被用来执行包含分数的数学运算
from fractions import Fraction
a = Fraction(5,4)
b = Fraction(3,4)
print(a)#5/4
print(a+b)#2
c = a * b
print(c)#15/16
print(c.numerator)#分子 15
print(c.denominator)#分母 16
print(float(c))#0.9375 将分数转换为小数
print(c.limit_denominator(7))#这个是什么意思
print(Fraction(*3.75.as_integer_ratio()))#将小数转换为分数 15/4
直接使用分数可以减少手动转换为小数或浮点数的工作。
3.9大型数组运算
涉及到数组的重量级运算操作,可以使用Numpy
库,Numpy
的一个主要特征是它会给Python提供一个数组对象,相比标准的Python列表更适合用来做数学运算,
#普通的py数组
x = [1,2,3,4]
y = [5,6,7,8]
print(x*2) #并不是对应元素的值乘以2,而是整体输出打印两次 [1, 2, 3, 4, 1, 2, 3, 4]
print(x+y) #并不是对应元素的和,而是列表的合并[1, 2, 3, 4, 5, 6, 7, 8]
# print(x * y)注意,这个会报错 TypeError: can't multiply sequence by non-int of type 'list'
#Numpy中的数组
import numpy as np
ax = np.array([1,2,3,4])
ay = np.array([5,6,7,8])
print(ax*2)#[2 4 6 8]
print(ax+ay)#[ 6 8 10 12]
print(ax*ay)#[ 5 12 21 32]
Numpy
中的标量运算(比如ax * 2
或ax+10
)会作用在每一个元素上。另外,当两个操作数都是数组的时候执行元素对等位置计算,并最终生成一个新的数组。
对整个数组中的所有元素同时执行数学运算可以使得作用在整个数组上的函数运算简单而又快速。
对整个数组中所有元素同时执行数学运算可以使得作用在整个数组上的函数运算简单而又快速。比如,如果你想计算多项式的值:
def f(x):
return 3*x**2 - 2*x + 7
print(f(ax))#[ 8 15 28 47]
Numpy
还为数组操作提供了大量的通用函数,这些函数可以作为math
模块中类似函数的替代
print(np.sqrt(ax))#[ 1. 1.41421356 1.73205081 2. ]
print(np.cos(ax))#[ 0.54030231 -0.41614684 -0.9899925 -0.65364362]
3.10矩阵与线性代数运算
执行矩阵和线性代数的运算,比如矩阵乘法、寻找行列式、求解线性方程组等等。
numpy
库有一个矩阵对象可以用来解决这个问题
m = np.matrix([[1,-2,3],[0,4,5],[7,8,-9]])
print(m)
print('矩阵的转置transpose')
print(m.T)
print('矩阵的逆inverse')
print(m.I)
print('Create a vector and multiply')
v = np.matrix([[2],[3],[4]])
print(v)
print('矩阵的乘法')
print(m*v)
输出如下
[[ 1 -2 3]
[ 0 4 5]
[ 7 8 -9]]
矩阵的转置transpose
[[ 1 0 7]
[-2 4 8]
[ 3 5 -9]]
矩阵的逆inverse
[[ 0.33043478 -0.02608696 0.09565217]
[-0.15217391 0.13043478 0.02173913]
[ 0.12173913 0.09565217 -0.0173913 ]]
Create a vector and multiply
[[2]
[3]
[4]]
矩阵的乘法
[[ 8]
[32]
[ 2]]
3.11随机选择
你想从一个序列中随机抽取若干元素,或者想生成几个随机数
random
模块有大量的函数用来生产随机数和随机选择元素。
可以使用random.choice()
来随机的抽取一个元素。使用random.sample()
来踢去出N个不同的元素
values = [1,2,3,4,5,6]
print(random.choice(values))#2 随机的
print(random.sample(values,3))#[5, 3, 4] 随机的
如果你想打乱序列中元素的位置,可以使用random.shuffle()
random.shuffle(values)
print(values)#[2, 4, 5, 1, 6, 3]
生成随机整数,可以使用random.randint()
生成0到1范围内均匀分布的浮点书,使用random.random()
如果要获取N位随机位(二进制)的整数,使用random.getrandbits()
print(random.randint(0,4))
print(random.random())
print(random.getrandbits(6))
random
模块使用Mersenne Twister算法来计算生成随机数。这是一个确定性算法,但是,你可以通过random.seed()
函数修改初始化种子。
除了上述功能,random模块还包括基于均匀分布、高斯分布的随机数生成函数。比如,random.uniform
计算均匀分布随机数,random.gauss()
计算正态分布随机数。
注:在random
模块中的函数不应该用在和密码学相关的程序中。如果你确实需要类似的功能,可以使用ssl模块中相应的函数。比如ssl.RAND_bytes()
可以用来生成一个安全的随机字节序列
3.12基本的日期与时间转换
当需要执行简单的时间转换,比如天到秒,小时到分钟等的转换的时候,可以使用datetime
模块。比如,为了表示一个时间短,可以创建一个timedelta
实例:
from datetime import timedelta
a = timedelta(days=2,hours=5)
b = timedelta(hours=4.5)
c = a + b
print(a)#2 days, 5:00:00
print(b.seconds)#16200
print(a.seconds)#18000
print(c.seconds/3600)#9.5 小时 并不包含天
print(c.total_seconds()/3600) # 57.5小时,包含天
如果你想表示指定的日期和时间,先创建一个datetime
实例,然后使用标准的数学运算来操作它们。
from datetime import datetime,timedelta
a = datetime(2017,7,11)
print(a+timedelta(days=10))#2017-07-21 00:00:00
b = datetime(2017,6,11)
d = a - b
print(d)#30 days, 0:00:00
now = datetime.today()
print(now)#2017-07-11 14:52:16.567548
print(now + timedelta(minutes=20))#2017-07-11 15:12:16.567548
在计算的时候,datetime
会自动处理闰年
对于大多数基本的日期和时间处理问题,datetime
模块已经足够了。如果你需要执行更加复杂的日期操作,比如处理时区,模糊时间范围,节假日计算等等,可以考虑使用dateutil模块
3.13计算最后一个周五的日期
from datetime import datetime,timedelta
from dateutil.relativedelta import relativedelta
from dateutil.rrule import *
now = datetime.now()
toady = datetime.today()
print(now)
print(toady)#2017-07-11 15:08:05.218067
print(now + relativedelta(weekday=FR))#2017-07-14 15:08:05.218055
print(now + relativedelta(weekday=FR(-1)))#2017-07-07 15:08:05.218055
3.14计算当前月份的日期范围
3.15字符串转换为日期
使用datetime
可以解决这个问题。
text = '2017-7-11'
y = datetime.strptime(text,'%Y-%m-%d')
print(y)
datetime.strptime()
方法支持很多的格式化代码,比如%Y
代表4位数年份,%m
代表两位数月份。并且,这个格式化占位符也可以反过来使用。