数字的四舍五入
问题:
你想对浮点数执行指定精度的舍入运算。
解决方法:
对于简单的舍入运算,使用内置的round(value, ndigits) 函数即可。比如:
1 #保留小数点后1位数,因为比1.25小,所以四舍五入,取小的 2 r1 = round(1.23, 1) 3 print(r1) 4 5 #保留小数点后1位数,因为比1.25大,所以四舍五入,所以取大的 6 r2 = round(1.27, 1) 7 print(r2) 8 9 #保留小数点后1位数,因为比-1.25小,所以四舍五入,所以取小的 10 r3 = round(-1.27, 1) 11 print(r3) 12 13 #保留小数点后3位数,因为比1.253大,所以四舍五入,所以取大的 14 r4 = round(1.25361, 3) 15 print(r4)
以上代码执行的结果为:
1.2 1.3 -1.3 1.254
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
执行精确的浮点数运算
问题:
你需要对浮点数执行精确的计算操作,并且不希望有任何小误差的出现。
解决方案:
浮点数的一个普遍问题是它们并不能精确的表示十进制数。并且,即使是最简单的数学运算也会产生小的误差,比如:
1 a = 4.2 2 b = 2.1 3 c = a + b 4 5 if c == 6.3: 6 print(‘True‘) 7 else: 8 print(‘False‘) 9 print(c) 10 11 #解决方案,如果你想更加精确(并能容忍一定的性能损耗),你可以使用decimal 模块 12 print(‘*‘*30) 13 from decimal import Decimal 14 a = Decimal(‘4.2‘) 15 b = Decimal(‘2.1‘) 16 c = a + b 17 print(c)
以上代码运行的结果为:
False 6.300000000000001 ****************************** 6.3
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
即便如此,你却不能完全忽略误差。数学家花了大量时间去研究各类算法,有些处理误差会比其他方法更好。你也得注意下减法删除已经大数和小数的加分运算所带来的影响。比如:
1 nums = [1.23e+18, 1, -1.23e+18] 2 #返回的结果是0.0,是错误的结果 3 print(‘错误的结果为:‘, sum(nums)) 4 5 #解决上面的问题办法 6 import math 7 print(‘正确的结果为:‘, math.fsum(nums))
以上代码运行的结果为:
错误的结果为: 0.0 正确的结果为: 1.0
总结:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
总的来说, decimal 模块主要用在涉及到金融的领域。在这类程序中,哪怕是一点小小的误差在计算过程中蔓延都是不允许的。因此, decimal 模块为解决这类问题提供了方法。当Python 和数据库打交道的时候也通常会遇到Decimal 对象,并且,通常也是在处理金融数据的时。
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
数字的格式化输出
问题:
你需要将数字格式化后输出,并控制数字的位数、对齐、千位分隔符和其他的细节。
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.5px Helvetica; color: #29556f }
解决方案:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
格式化输出单个数字的时候,可以使用内置的format() 函数,比如:
1 x = 1234.56789 2 print(format(x, ‘0.2f‘)) 3 4 #右对齐10个字符并保留小数点后一位 5 print("右对齐十个字符:", format(x, ‘>10.1f‘)) 6 7 #左对齐10个字符并保留小数点后一位 8 print("左对齐十个字符:", format(x, ‘<10.1f‘) + ‘!‘) 9 10 #居中对齐 11 print("居中对齐十个字符:", format(x, ‘^10.1f‘)) 12 13 #分离器,分离千万 14 print("分离的格式:", format(x, ‘,‘)) 15 16 print(format(x, ‘0,.1f‘))
以上代码运行的结果为:
1234.57 右对齐十个字符: 1234.6 左对齐十个字符: 1234.6 ! 居中对齐十个字符: 1234.6 分离的格式: 1,234.56789 1,234.6
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
二八十六进制整数
问题:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
你需要转换或者输出使用二进制,八进制或十六进制表示的整数。
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.5px Helvetica; color: #29556f }
解决方案:
为了将整数转换为二进制、八进制或十六进制的文本串,可以分别使用bin() ,oct() 或hex() 函数:
1 x = 1234 2 3 #二进制格式的 4 print(bin(x)) 5 6 #八进制格式的 7 print(oct(x)) 8 9 #十六进制格式的 10 print(hex(x)) 11 12 #如果你不想输出0b , 0o 或者0x 的前缀的话,可以使用format() 函数 13 print(format(x, ‘b‘)) 14 print(format(x, ‘o‘)) 15 print(format(x, ‘x‘))
以上代码运行的结果为:
0b10011010010 0o2322 0x4d2 10011010010 2322 4d2
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
字节到大整数的打包与解包
问题:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
你有一个字节字符串并想将它解压成一个整数。或者,你需要将一个大整数转换为一个字节字符串。
解决方案:
假设你的程序需要处理一个拥有128 位长的16 个元素的字节字符串。比如:
1 data = b‘\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004‘ 2 3 print(‘data的长度为:‘, len(data)) 4 5 r1 = int.from_bytes(data, ‘little‘) 6 print(r1) 7 8 r2 = int.from_bytes(data, ‘big‘) 9 print(r2) 10 11 #为了将一个大整数转换为一个字节字符串,使用int.to bytes() 方法,并像下面这样指定字节数和字节顺序 12 x = 94522842520747284487117727783387188 13 r3 = x.to_bytes(16, ‘big‘) 14 print(r3) 15 16 r4 = x.to_bytes(16, ‘little‘) 17 print(r4)
以上代码运行的结果为:
data的长度为: 16 69120565665751139577663547927094891008 94522842520747284487117727783387188 b‘\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004‘ b‘4\x00#\x00\x01\xef\xcd\x00\xab\x90x\x00V4\x12\x00‘
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
分数运算
问题:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
你进入时间机器,突然发现你正在做小学家庭作业,并涉及到分数计算问题。或者你可能需要写代码去计算在你的木工工厂中的测量值。
解决方案:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
fractions 模块可以被用来执行包含分数的数学运算。比如:
1 from fractions import Fraction 2 3 #除法 等同于5/4 7/16 4 a = Fraction(5, 4) 5 b = Fraction(7, 16) 6 7 r1 = a * b 8 print(a + b) 9 print(a * b) 10 11 #被除数 12 r = a * b 13 print(r.numerator) 14 15 #除数 16 print(r.denominator) 17 18 #结果 19 print(float(r))
以上代码运行的结果为:
27/16 35/64 35 64 0.546875
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
大型数组运算
问题:
你需要在大数据集(比如数组或网格) 上面执行计算
解决方案:
涉及到数组的重量级运算操作,可以使用NumPy 库。NumPy 的一个主要特征是它会给Python 提供一个数组对象,相比标准的Python 列表而已更适合用来做数学运算。下面是一个简单的小例子,向你展示标准列表对象和NumPy 数组对象之间的差别:
1 x = [1, 2 ,3 , 4, 5] 2 y = [6, 7, 8, 9, 10] 3 4 #x列表的乘以2的效果 5 print("x*2:", x * 2) 6 7 #做列表拼接 8 print(‘x+y:‘, x + y) 9 10 import numpy as np 11 # print("数组".center(40, "*")) 12 print(‘{:*^40}‘.format(‘数组‘)) 13 14 ax = np.array([1, 2, 3, 4]) 15 ay = np.array([5, 6, 7, 8]) 16 17 #数组的每个元素都乘以2 18 print(‘ax*2 :‘, ax * 2) 19 print(‘ax+10:‘, ax + 10) 20 print(‘ax+ay:‘, ax + ay) 21 print(‘ax*ay:‘, ax * ay)
以上代码运行的结果为:
x*2: [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] x+y: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] *******************数组******************* ax*2 : [2 4 6 8] ax+10: [11 12 13 14] ax+ay: [ 6 8 10 12] ax*ay: [ 5 12 21 32]
总结:
正如所见,两种方案中数组的基本数学运算结果并不相同。特别的, NumPy 中的标量运算(比如ax * 2 或ax + 10 ) 会作用在每一个元素上。另外,当两个操作数都是数组的时候执行元素对等位置计算,并最终生成一个新的数组。
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
矩阵与线性代数运算
问题:
你需要执行矩阵和线性代数运算,比如矩阵乘法、寻找行列式、求解线性方程组等等。
解决方案:
NumPy 库有一个矩阵对象可以用来解决这个问题。
1 import numpy as np 2 3 m = np.matrix([[1, -2, 3], [0, 4, 5], [7, 8, 9]]) 4 5 print(m.T) 6 print(‘‘.center(40, ‘*‘)) 7 8 print(m.I) 9 print(‘‘.center(40, ‘-‘)) 10 11 v = np.matrix([[2], [3], [4]]) 12 print(v) 13 14 print(‘‘.center(40, ‘~‘)) 15 print(m * v)
以上代码运行的结果为:
[[ 1 0 7] [-2 4 8] [ 3 5 9]] **************************************** [[ 0.02531646 -0.26582278 0.13924051] [-0.22151899 0.07594937 0.03164557] [ 0.17721519 0.13924051 -0.02531646]] ---------------------------------------- [[2] [3] [4]] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [[ 8] [32] [74]]
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
随机选择
问题:
你想从一个序列中随机抽取若干元素,或者想生成几个随机数。
解决方案:
random 模块有大量的函数用来产生随机数和随机选择元素。比如,要想从一个序列中随机的抽取一个元素,可以使用random.choice() :
1 import random 2 3 values = list(range(10)) 4 5 #从values中提取单个元素 6 print(‘提取单个元素‘.center(15, ‘*‘)) 7 print(random.choice(values)) 8 print(random.choice(values)) 9 print(random.choice(values)) 10 print(random.choice(values)) 11 12 #从values中提取N个不同的元素 13 print(‘提取N个元素‘.center(15, ‘*‘)) 14 print(random.sample(values, 3)) 15 print(random.sample(values, 3)) 16 print(random.sample(values, 3)) 17 18 print(‘打乱values的元素顺序‘.center(15, ‘*‘)) 19 print(‘打乱之前的values:‘, values) 20 random.shuffle(values) 21 print("打乱以后的values:", values)
以上代码运行的结果为:
*****提取单个元素**** 1 2 7 0 *****提取N个元素**** [3, 5, 0] [4, 8, 2] [4, 9, 3] *打乱values的元素顺序* 打乱之前的values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 打乱以后的values: [1, 8, 7, 2, 9, 5, 3, 4, 0, 6]
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
基本的日期与时间转换
问题:
你需要执行简单的时间转换,比如天到秒,小时到分钟等的转换。
解决方案:
为了执行不同时间单位的转换和计算,请使用datetime 模块。比如,为了表示一个时间段,可以创建一个timedelta 实例,就像下面这样:
1 from datetime import timedelta, datetime 2 3 a = timedelta(days=2, hours=6) 4 b = timedelta(hours=4.5) 5 c = a + b 6 7 print(‘biubiu天~:‘, c.days) 8 9 print(‘biubiu秒~:‘, c.seconds) 10 11 print(‘小时:‘, c.seconds / 3600) 12 13 print(‘总共经过多少小时:‘, c.total_seconds() / 3600) 14 15 a1 = datetime(2017, 8, 3) 16 #在当前时间上加10天 17 print(a1 + timedelta(days=10)) 18 19 b1 = datetime(2017, 12, 21) 20 c1 = b1 - a1 21 #两个时间点相差多少天 22 print(c1) 23 24 print(c1.days) 25 26 print(‘当前时间‘.center(30, ‘*‘)) 27 now = datetime.today() 28 print(now) 29 30 print(‘当前时间往后推8个小时‘.center(26,"*")) 31 print(now + timedelta(hours=8)) 32 33 print(‘当前时间往后推30分钟‘.center(27, ‘*‘)) 34 print(now + timedelta(minutes=30))
以上代码运行的结果为:
biubiu天~: 2 biubiu秒~: 37800 小时: 10.5 总共经过多少小时: 58.5 2017-08-13 00:00:00 140 days, 0:00:00 140 *************当前时间************* 2017-08-03 14:42:28.002825 *******当前时间往后推8个小时******** 2017-08-03 22:42:28.002825 ********当前时间往后推30分钟******** 2017-08-03 15:12:28.002825
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
计算最后一个周五的日期
问题:
你需要查找星期中某一天最后出现的日期,比如星期五。
解决方案:
Python 的datetime 模块中有工具函数和类可以帮助你执行这样的计算。下面是对类似这样的问题的一个通用解决方案:
1 from datetime import datetime, timedelta 2 3 weekdays = [‘Monday‘, ‘Tuesday‘, ‘Wednesday‘, ‘Thursday‘, 4 ‘Friday‘, ‘Saturday‘, ‘Sunday‘] 5 6 def get_previous_byday(dayname, start_date=None): 7 if start_date is None: 8 start_date = datetime.today() 9 day_num = start_date.weekday() 10 day_num_target = weekdays.index(dayname) 11 days_ago = (7 + day_num - day_num_target) % 7 12 if days_ago == 0: 13 days_ago = 7 14 target_date = start_date - timedelta(days=days_ago) 15 return target_date 16 17 18 print(get_previous_byday(‘Monday‘)) 19 print(get_previous_byday(‘Tuesday‘)) 20 print(get_previous_byday(‘Friday‘)) 21 get_previous_byday(‘Sunday‘, datetime(2017, 12, 21))
以上代码运行的结果为:
2017-07-31 14:58:38.092831 2017-08-01 14:58:38.092945 2017-07-28 14:58:38.092975 2017-12-24 00:00:00
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
上面的算法原理是这样的:先将开始日期和目标日期映射到星期数组的位置上(星期一索引为0),然后通过模运算计算出目标日期要经过多少天才能到达开始日期。然后用开始日期减去那个时间差即得到结果日期
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
计算当前月份的日期范围
问题:
你的代码需要在当前月份中循环每一天,想找到一个计算这个日期范围的高效方法
解决方案:
在这样的日期上循环并需要事先构造一个包含所有日期的列表。你可以先计算出开始日期和结束日期,然后在你步进的时候使用datetime.timedelta 对象递增这个日期变量即可
1 from datetime import datetime, date , timedelta 2 import calendar 3 4 def get_month_range(start_date=None): 5 if start_date is None: 6 start_date = date.today().replace(day=1) 7 _, days_in_month = calendar.monthrange(start_date.year, start_date.month) 8 end_date = start_date + timedelta(days=days_in_month) 9 return (start_date, end_date) 10 11 a_day = timedelta(days=1) 12 first_day, last_day = get_month_range() 13 14 while first_day < last_day: 15 print(first_day) 16 first_day += a_day
以上代码运行的结果为:
017-08-01 2017-08-02 2017-08-03 2017-08-04 2017-08-05 2017-08-06 2017-08-07 2017-08-08 ................
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Helvetica; color: #29556f }
结合时区的日期操作
问题:
你有一个安排在2012 年12 月21 日早上9:30 的电话会议,地点在芝加哥。而你的朋友在印度的班加罗尔,那么他应该在当地时间几点参加这个会议呢?
解决方案:
对几乎所有涉及到时区的问题,你都应该使用pytz 模块。这个包提供了Olson 时区数据库,它是时区信息的事实上的标准,在很多语言和操作系统里面都可以找到
1 from datetime import datetime 2 from pytz import timezone, utc 3 4 #初始化时间 5 d = datetime(2017, 8, 3, 11, 20, 38) 6 print("本地时间:", d) 7 8 #转换成芝加哥时间 9 central = timezone("US/Central") 10 loc_d = central.localize(d) 11 print("芝加哥的时间:", loc_d) 12 13 #班加罗尔的时间 pytz.utc是utc时间,asctimezone中可以替换成这个 14 bang_d = loc_d.astimezone(timezone(‘Asia/Kolkata‘)) 15 #bang_d = loc_d.astimezone(utc) 16 print("班加罗尔的时间:", bang_d)
以上代码运行的结果为:
本地时间: 2017-08-03 11:20:38 芝加哥的时间: 2017-08-03 11:20:38-05:00 班加罗尔的时间: 2017-08-03 21:50:38+05:30
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }