n 以內能被 m 整除的數的和、積
最初版本
計算指定數字內所有偶數的和
n = int(input("請輸入指定的n:"))
i = 0
mysum = 0
while i <= n:
if i % 2 == 0:
mysum = mysum + i
i = i + 1
print(f"{n}以內的所有偶數的和是{mysum}")
print("{0}以內的所有偶數的和是{1}".format(n, mysum))
對于兩行輸出代碼:
第一行代碼使用了 f-string,語法形式為在字串前加上字母 f,然后使用花括號 {} 括起來的變數名或運算式,就可以在字串中插入變數的值,在這個例子中,f-string 會將變數 n 和 mysum 的值插入到字串中,
第二行代碼使用了字串的 format() 方法,它可以用來替換字串中的占位符,在這個例子中,字串中的占位符是 {0} 和 {1},分別對應 format() 方法的第一個引數和第二個引數,在 format() 方法中,可以按照順序傳遞引數值,或者使用關鍵字引數來指定引數的位置,輸出結果與 f-string 相同
優化方法
使用 for 回圈
n = int(input("請輸入指定的n"))
mysum = 0
for i in range(0, n+1, 2):
mysum += i
print(f"{n}以內的所有偶數的和是{mysum}")
使用串列推導式
n = int(input("請輸入指定的n:"))
mysum = sum([i for i in range(n+1) if i % 2 == 0])
print(f"{n}以內的所有偶數的和是{mysum}")
使用內置 math 模塊
import math
n = int(input("請輸入指定的n:"))
mysum = math.ceil(n/2) * (n//2 + 1)
print(f"{n}以內的所有偶數的和是{mysum}")
使用 math.ceil() 函式來將 n 除以 2 并向上取整,這里使用向上取整的原因是為了確保當 n 為奇數時,也能夠正確計算偶數和,例如,當 n 為 5 時,5//2 = 2,2*3 = 6,這樣就能正確計算 5 以內的偶數和了,
使用整除運算子 // 和取模運算子 % 來計算 n 的一半和 n 的下取整值,然后將它們相乘得到所有偶數的和,這個計算公式的思路是:偶數和 = 2 + 4 + 6 + ... + n(n 為偶數)= 2 * (1 + 2 + 3 + ... + n/2) = 2 * [n/2 * (n/2 + 1)/2] = n/2 * (n/2 + 1),其中 [ ] 表示向下取整,注意,當 n 為奇數時,n//2 會向下取整,因此會忽略掉最后一個奇數,但這并不影響結果,因為最后一個奇數一定不是偶數,
使用 peephole 優化技術
n = int(input("請輸入指定的n:"))
i = 0
mysum = 0
while i <= n:
if not i & 1: # 使用位運算代替求余運算
mysum += i # 使用增量賦值代替普通賦值
i += 1
print(f"{n}以內的所有偶數的和是{mysum}")
在 Python 中,位運算比求余運算更快,因此可以提高代碼的執行效率,在這個例子中,使用了位運算 & 來判斷 i 是否為偶數,由于偶數的二進制表示的最后一位為 0,因此 i & 1 的結果為 0 就意味著 i 是偶數,這樣就避免了使用 % 運算子來求余數,提高了代碼的性能,
使用了增量賦值 += 代替普通賦值,增量賦值可以將兩個操作合并成一個,從而提高代碼的執行效率,
這些優化方法可能對于小規模的資料集并沒有太大的作用,但是在處理大規模資料集時,它們能夠提高代碼的執行效率,從而減少程式的運行時間和資源消耗,
關于位運算
當我們將一個二進制數和 1 進行按位與(&)操作時,只有最后一位是 1 的二進制數和 1 進行按位與操作的結果是 1,其余情況下結果都是 0,
如果一個數是偶數,它的二進制表示的最后一位是 0,那么它和 1 進行按位與操作的結果也是 0;
如果一個數是奇數,它的二進制表示的最后一位是 1,那么它和 1 進行按位與操作的結果就是 1,
需要注意的是,在進行位運算時,應該使用位運算子 &、|、^ 和 ~,而不是邏輯運算子 and、or 和 not,因為位運算子是針對二進制數的,它們操作的是二進制數的每一位,而邏輯運算子是針對布林值的,它們操作的是 True 和 False,
進階版本 1
n = int(input("請輸入指定的n:"))
m = int(input("請輸入指定的m:"))
sum_divisible_by_m = sum([i for i in range(m, n+1) if i % m == 0])
product_divisible_by_m = 1
for i in range(m, n+1):
if i % m == 0:
product_divisible_by_m *= i
print(f"{n}以內能被{m}整除的數的和是{sum_divisible_by_m}")
print(f"{n}以內能被{m}整除的數的積是{product_divisible_by_m}")
這段代碼首先通過 input() 函式獲取用戶輸入的 n 和 m,然后分別使用 sum() 函式和 for 回圈來計算小于等于 n 且能被 m 整除的數的和和積,
需要注意的是,第 4 行代碼中的串列推導式中的 range() 函式使用了起始值 m,這是為了確保生成的串列中的第一個元素是能被 m 整除的數,同時,第 5 行代碼中的 for 回圈也從 m 開始遍歷,這是為了避免重復計算 m,如果不從 m 開始遍歷,那么 m 就會被計算兩次,一次在串列推導式中,一次在 for 回圈中,
在 Python 中沒有內置的連乘函式,但可以通過使用內置函式 reduce() 或者 NumPy 庫中的 prod() 函式來實作連乘,
reduce() 函式
reduce() 函式位于 functools 模塊中,它可以對一個序列中的元素進行累積計算,
from functools import reduce
product = reduce(lambda x, y: x * y, [1, 2, 3, 4, 5])
print(product) # 輸出 120
使用 reduce() 函式將串列 [1, 2, 3, 4, 5] 中的所有元素累乘起來,reduce() 函式接受兩個引數:一個函式和一個序列,函式用于對序列中的元素進行累積計算,序列是要計算的元素,在這個例子中,我們使用 lambda 運算式定義了一個匿名函式來計算累乘結果,然后將這個函式和串列 [1, 2, 3, 4, 5] 傳遞給 reduce() 函式,
prod() 函式
如果需要對 NumPy 陣列進行連乘計算,可以使用 NumPy 庫中的 prod() 函式,
import numpy as np
product = np.prod([1, 2, 3, 4, 5])
print(product) # 輸出 120
修改后的結果
from functools import reduce
n = int(input("請輸入指定的n:"))
m = int(input("請輸入指定的m:"))
sum_divisible_by_m = sum([i for i in range(m, n+1, m)])
product_divisible_by_m = reduce(lambda x, y: x * y, range(m, n+1, m), 1)
print(f"{n}以內能被{m}整除的數的和是{sum_divisible_by_m}")
print(f"{n}以內能被{m}整除的數的積是{product_divisible_by_m}")
- lambda是一種創建匿名函式的方式,它可以讓你在一行代碼中定義一個簡單的函式,而不需要使用def關鍵字,lambda函式的語法是
lambda 引數: 運算式,它表示一個接受引數并回傳運算式計算結果的函式,例如,lambda x, y: x * y就是一個接受兩個引數x和y,并回傳它們相乘結果的函式, - reduce是一個內置函式,它可以對一個可迭代物件(如串列)中的元素進行累積操作,從而得到一個單一的值,reduce函式的語法是
reduce(函式, 可迭代物件, 初始值),它表示從左到右依次將可迭代物件中的元素和初始值作為引數傳遞給函式,并將函式的回傳值作為下一次呼叫的初始值,直到可迭代物件中的元素遍歷完畢,例如,reduce(lambda x, y: x + y, [1, 2, 3, 4], 0)就是對串列[1, 2, 3, 4]中的元素進行求和操作,并以0作為初始值,最終得到10,
代碼reduce(lambda x, y: x * y, range(m, n + 1, m), 1)是什么意思呢?
range(m, n + 1, m)是一個生成器,它可以產生從m到n(包含n)之間以m為步長的整數序列,lambda x, y: x * y是一個接受兩個引數x和y,并回傳它們相乘結果的函式,reduce(lambda x, y: x * y, range(m, n + 1, m), 1)就是對range(m, n + 1, m)中的元素進行累乘操作,并以1作為初始值,例如,如果m=2,n=10,那么這個運算式就相當于計算(1 * 2 * 4 * 6 * 8 * 10),最終得到3840,
需要注意的是,代碼中的 range() 函式使用了步長 m,這是為了確保生成的序列中的所有元素都能被 m 整除,同時,第 5 行代碼中的串列推導式中的 range() 函式也使用了步長 m,這是為了避免重復計算,如果不使用步長 m,那么就會生成一個包含所有小于等于 n 的數的串列,然后再篩選出能被 m 整除的數,這樣就會浪費一些時間和空間,
進階版本 2
import numpy as np
from functools import reduce
# 輸入檢查:確保 n 和 m 都是正整數
while True:
try:
n = int(input("請輸入指定的 n:"))
m = int(input("請輸入指定的 m:"))
if n > 0 and m > 0:
break
else:
print("n 和 m 必須是正整數,請重新輸入")
except ValueError:
print("n 和 m 必須是正整數,請重新輸入")
# 如果 n 太大,就使用 1000000 代替
if n > 1000000:
n = 1000000
print("n 太大,已經自動調整為 1000000")
# 計算能被 m 整除的數的和和積
sum_divisible_by_m = sum([i for i in range(m, n+1, m)])
product_divisible_by_m = reduce(lambda x, y: x * y, range(m, n+1, m), 1)
product_divisible_by_m1 = np.prod(range(m, n+1, m))
# 輸出結果
print(f"{n} 以內能被 {m} 整除的數的和是 {sum_divisible_by_m}")
print(f"{n} 以內能被 {m} 整除的數的積是 {product_divisible_by_m}")
print(f"{n} 以內能被 {m} 整除的數的積是 {product_divisible_by_m1}")
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/549957.html
標籤:Python
上一篇:11函式入門
下一篇:12函式進階
