1. 程式人生 > >數字日期和時間

數字日期和時間

正在 作業 fff 數學家 nds num hour 開始 tro

數字的四舍五入

問題:

  你想對浮點數執行指定精度的舍入運算。

解決方法:

  對於簡單的舍入運算,使用內置的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\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
b4\x00#\x00\x01\xef\xcd\x00\xab\x90x\x00V4\x12\x00

分數運算

問題:

  你進入時間機器,突然發現你正在做小學家庭作業,並涉及到分數計算問題。或者你可能需要寫代碼去計算在你的木工工廠中的測量值。

解決方案:

  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

數字日期和時間