数字日期和时间

数字的四舍五入

问题:

  你想对浮点数执行指定精度的舍入运算。

解决方法:

  对于简单的舍入运算,使用内置的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

执行精确的浮点数运算

问题:

  你需要对浮点数执行精确的计算操作,并且不希望有任何小误差的出现。

解决方案:

  浮点数的一个普遍问题是它们并不能精确的表示十进制数。并且,即使是最简单的数学运算也会产生小的误差,比如:

 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

即便如此,你却不能完全忽略误差。数学家花了大量时间去研究各类算法,有些处理误差会比其他方法更好。你也得注意下减法删除已经大数和小数的加分运算所带来的影响。比如:

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

总结:

  总的来说, decimal 模块主要用在涉及到金融的领域。在这类程序中,哪怕是一点小小的误差在计算过程中蔓延都是不允许的。因此, decimal 模块为解决这类问题提供了方法。当Python 和数据库打交道的时候也通常会遇到Decimal 对象,并且,通常也是在处理金融数据的时。

数字的格式化输出

问题:

  你需要将数字格式化后输出,并控制数字的位数、对齐、千位分隔符和其他的细节。

解决方案:

  格式化输出单个数字的时候,可以使用内置的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

二八十六进制整数

问题:

  你需要转换或者输出使用二进制,八进制或十六进制表示的整数。

 

解决方案:

  为了将整数转换为二进制、八进制或十六进制的文本串,可以分别使用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

字节到大整数的打包与解包

问题:

  你有一个字节字符串并想将它解压成一个整数。或者,你需要将一个大整数转换为一个字节字符串。

解决方案:

  假设你的程序需要处理一个拥有128 位长的16 个元素的字节字符串。比如:

 1 data = b'x00x124Vx00xx90xabx00xcdxefx01x00#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'x00x124Vx00xx90xabx00xcdxefx01x00#x004'
b'4x00#x00x01xefxcdx00xabx90xx00V4x12x00'

分数运算

问题:

  你进入时间机器,突然发现你正在做小学家庭作业,并涉及到分数计算问题。或者你可能需要写代码去计算在你的木工工厂中的测量值。

解决方案:

  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

大型数组运算

问题:

  你需要在大数据集(比如数组或网格) 上面执行计算

解决方案:

  涉及到数组的重量级运算操作,可以使用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 ) 会作用在每一个元素上。另外,当两个操作数都是数组的时候执行元素对等位置计算,并最终生成一个新的数组。

矩阵与线性代数运算

问题:

  你需要执行矩阵和线性代数运算,比如矩阵乘法、寻找行列式、求解线性方程组等等。

解决方案:

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

随机选择

问题:

  你想从一个序列中随机抽取若干元素,或者想生成几个随机数。

解决方案:

  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]

基本的日期与时间转换

问题:

  你需要执行简单的时间转换,比如天到秒,小时到分钟等的转换。

解决方案:

  为了执行不同时间单位的转换和计算,请使用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

计算最后一个周五的日期

问题:

  你需要查找星期中某一天最后出现的日期,比如星期五。

解决方案:

  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

上面的算法原理是这样的:先将开始日期和目标日期映射到星期数组的位置上(星期一索引为0),然后通过模运算计算出目标日期要经过多少天才能到达开始日期。然后用开始日期减去那个时间差即得到结果日期

 

计算当前月份的日期范围

问题:

  你的代码需要在当前月份中循环每一天,想找到一个计算这个日期范围的高效方法

解决方案:

  在这样的日期上循环并需要事先构造一个包含所有日期的列表。你可以先计算出开始日期和结束日期,然后在你步进的时候使用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
................

结合时区的日期操作

问题:

  你有一个安排在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
原文地址:https://www.cnblogs.com/demon89/p/7274490.html