使用者:Xyy23330121/Python/數字
Python 具有三種數字對象:整數int
、浮點數float
和複數complex
,其中複數可以被認為是分別表示實部和虛部的兩個浮點數組成的。浮點數可以簡單理解為小數。
可以用以下方式給變量賦值。
a = 1 #整数 1
b = 1.0 #浮点数 1.0
c = 1 + 0j #复数 1.0+0j
通過type
函數,可以查閱變量的類型[1]。比如:
print(type(a),type(b),type(c))
,
為分隔,可以給支持多個參數的函數傳入多個參數。print
函數就支持多個參數,它可以同時輸出多個參數的內容,並以空格分隔[2]。
參數按順序傳入,比如
print("a","b")
和print("b","a")
輸出的結果是不同的,即便傳入了排列不同的相同參數。運行以上代碼的結果為:
<class 'int'> <class 'float'> <class 'complex'>
一些基本運算符如下:
print(2 + 1, type(2 + 1)) # 加法运算,输出为:3 <class 'int'>
print(2 - 1, type(2 - 1)) # 减法运算,输出为:1 <class 'int'>
print(2 * 1, type(2 * 1)) # 乘法运算,输出为:2 <class 'int'>
print(2 / 1, type(2 / 1)) # 除法运算,输出为:2.0 <class 'float'>
print(2 ** 1, type(2 ** 1)) # 幂运算,输出为:2 <class 'int'>
print(2 // 1, type(2 // 1)) # 带余除法求商,输出为:2 <class 'int'>
print(2 % 1, type(2 % 1)) # 带余除法求余,输出为:0 <class 'int'>
print(divmod(2,1)) # 同时输出带余除法的商和余数
Python 在進行計算時,會先將所有數字轉化成可能需要的、最「通用」的類型。浮點數比整數通用,複數比浮點數通用。比如:
- 當整數和整數進行計算時,結果一般是兩者之間最通用的類型:整數;
- 當整數和浮點數進行計算時,結果一定是兩者之間最通用的類型:浮點數;
- 當整數和複數進行計算時,結果一定是兩者之間最通用的類型:複數。
以上內容只有兩個例外,就是:
- 整數和整數之間的除法一定會返回浮點數。
- 整數的負整數次冪會返回浮點數。
Python 作除法時,除數不能為零。如果輸入:
1 / 0
Python 會報告一個錯誤:
ZeroDivisionError: division by zero
abs
函數會返回數字的絕對值。對於複數而言,會返回複數的模。
print(abs(-2)) #输出:2
print(abs(2.0)) #输出:2.0
print(abs(3+4j)) #输出:5.0
從上述結果可以看出。對於整數求絕對值,會返回一個整數;對於浮點數或複數求絕對值,會返回一個浮點數。
對於複數,可以單獨取出其實部和虛部。
c = 1 + 2.3j
print(c.real) #c.real会输出c的实部,此例为1.0
print(c.imag) #c.imag会输出c的虚部,此例为2.3
Python 允許創建無窮大或 NaN 。NaN 是 Not a Number 的簡稱。有些程式語言在遇到除數為零時會返回「無窮大」或「NaN」。但 Python 嚴格限制除數不能為零,所以這兩個數字不能直接用除數為零的表達式生成。
可以用以下方法創建無窮大或 NaN :
a = float("inf") #创建正无穷。也可以用float("infinity")。
b = float("-inf") #创建负无穷。也可以用float("-infinity")
c = float("nan") #创建NaN。
其中的字符串大小寫不敏感,以正無窮為例,寫成float("InF")
或float("iNFinity")
等方式也是可以的。
除一般的計算之外。無窮大的運算遵循以下法則:
- 無窮大和零作乘法,結果為NaN。
- 正無窮大和負無窮大作加法,結果為NaN。
而NaN無論進行什麼計算,結果均為NaN。
由於複數可以被認為是由兩個浮點數組成的,複數和無窮大以及複數和NaN的計算,計算後得到的實部和虛部兩個浮點數,也都分別滿足以上性質。
特別的,NaN 在比較運算符的表現很奇怪:
inf, nan = float("inf"), float("nan")
res = inf * 0; print(res, res == nan) #输出:nan False
res = inf - inf; print(res, res == nan) #输出:nan False
整數的帶餘除法很好理解。浮點數的帶餘除法與整數的帶餘除法類似。
對於整數 和正整數 。存在唯一的一對整數 和 ,滿足以下算式:
我們稱 是商, 是餘數。
對於被除數 或除數 之一為浮點數時而言,以上算式同樣有效,不過需要把 也變成浮點數,而把 變成用浮點數表示的整數。我們看以下示例:
print(-1.0//0.3 , -1.0%0.3)
其輸出為:
-4.0 0.19999999999999996
即帶餘除法的商為-4,用浮點數表示為-4.0
,而餘數為0.2,由於計算精度的問題,輸出為0.19999999999999996
。
Python 的 %
運算,在除數 b
為負數時,設置餘數為負數。此時,算式改為:
此函數也會返回一類帶餘除法的餘數。
與 %
運算符不同,math.fmod
返回的餘數、和被除數 x
的符號相同。
在被除數遠小於除數時,這種方法的精度比 %
運算要高。因為:
import math
print(math.fmod(-1e-100,1e100)) #结果为:-1e-100
print(-1e-100 % 1e100) #结果为:1e100-1e-100,并舍入为:1e100
所以,作浮點數帶餘除法時,更推薦使用 math.fmod
而不是 %
。
此函數也會返回一類不同的帶餘除法的餘數。
與上述的兩種運算不同,這種方法對商有規定:它會將 round(x/y)
設為商,然後再將 x - round(x/y) * y
設為餘數。
這種帶餘除法,是 IEEE 754 風格的帶餘除法。
除簡單的計算而言,Python 支持一些簡便寫法。
a = 0
a += 1 #等同于 a = a + 1
其中,+=
被稱為是賦值運算符。類似的,其他運算也有賦值運算符。
a = 0
a += 4 #此时a = 4
print(a)
a -= 2 #此时a = 2
print(a)
a *= 12 #此时a = 24
print(a)
a /= 3 #此时a = 8.0
print(a)
a //= 2 #此时a = 4.0
print(a)
a %= 5 #此时a = 4.0
print(a)
a **= 0.5 #此时 a = 2.0
print(a)
除以上運算符之外,Python 還提供了一個內置的數學運算模塊。該模塊對浮點數和整數支持一些基本的運算。以下將簡單介紹該模塊當中一些常用的函數和變量。
import math
#取整
a, b = 1.5, -0.5
A, B = math.ceil(a), math.ceil(b) #math.ceil函数用于向上取整,会返回不小于其中数字的最小整数
print(A,B) #输出为:2, 0
A, B = math.floor(a), math.floor(b) #math.floor函数用于向下取整,会返回不大于其中数字的最大整数
print(A,B) #输出为:1, -1
A, B = math.tunc(a), math.trunc(b) #math.trunc函数用于向零取整,会去除数字的小数部分
print(A,B) #输出为:1, 0
#数学常量
print(math.e) #输出为:2.718281...
print(math.pi) #输出为:3.141592...
math 模塊還提供了三角函數等多個實用函數。關於 math 模塊中的其他函數和變量,請參閱 Python 文檔,這裡不再列出。在一些情況下,math 模塊中的一些函數,其誤差要比運算符要小。所以當需要高精度計算的時候,請多查閱 math 模塊的文檔,可能能發現精度更高的方法。
類似,還有 cmath 模塊用於處理複數的一些運算,詳情請參閱cmath模塊的Python文檔
Python 提供了幾種簡單的函數,可以利用已有對象,創建對應的的數字對象。
函數int
可以將內容轉化為整數。比如:
print(int(1.23)) #结果:1
print(int(-1.23)) #结果:-1
print(int(" 1023")+1) #结果:1024
print(int(1)) #结果:1
int
函數可以將浮點數或字符串轉化為整數。如果把字符串轉化為整數,被轉化的字符串主要部分只能包含0
至9
以及+
、-
,位於主要部分前後的空格和換行符\n
等會被忽略。對於浮點數,該函數輸出的結果為向零取整的結果。
對於已經是整數的內容,int
函數會直接輸出其自身。
如果輸入的內容不符合要求,比如輸入了複數或錯誤的字符串,程序會報錯退出。
比如:int("1 23")
、int("1-23")
和int("1.23")
會報錯:
ValueError: invalid literal for int() with base 10
而int(1+0j)
會報錯:
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'complex'
float
函數可以將內容轉化為浮點數。比如:
print(float(1)) #结果:1.0
print(float("1.23")) #结果:1.23
print(float("-123e-2")) #结果:-1.23
1.23e-4
的字符串,表示的是科學計數法 的意思。float
函數可以將整數或字符串轉化為浮點數。如果要轉化字符串,字符串除了可以為表示整數、小數的字符串,也可以是科學計數法表示的浮點數。
還有一些其他形式的字符串可以被float
函數轉化。比如上面選學章節提到過的float("inf")
。
與int
函數相同,位於首尾的空格和換行符會被忽略。而且,如果輸入的內容不符合要求,比如輸入了複數或錯誤的字符串,程序會報錯退出。
print(complex(1)) #结果:1.0+0.0j
print(complex("1.23")) #结果:1.23+0.0j
print(complex("-123e-2+1j")) #结果:-1.23+1.0j
轉化為複數的complex
函數和轉化為浮點數的float
函數是類似的。但是要注意,主要部分不能有空格。比如以下的代碼會報錯:
print(complex("-123e-2 + 1j"))
除上述方法之外,還可以輸入兩個整數或浮點數的參數來生成複數:
print(complex(1, 2)) #结果:1.0+2.0j
print(complex(1.1, 2.1)) #结果:1.1+2.1j
input
函數可以在程序運行時輸入字符串內容。比如運行以下代碼:
c = input()
print("输入的内容:",c)
在程序運行時,輸入 aabbcc
並按回車後,程序會輸出:
输入的内容: aabbcc
同時,input
函數還可以給出提示。比如:
c = input("请输入内容:")
print("输入的内容:",c)
在程序運行時,會先輸出:
请输入内容:
此時,輸入 aabbcc
並按回車後,程序會輸出:
输入的内容: aabbcc
了解了以上內容後,作為練習,我們可以寫一個運算浮點數加法的程序。
#!/usr/bin/python
# -*- coding: utf-8 -*-
a = float(input("请输入第 1 个数字:"))
b = float(input("请输入第 2 个数字:"))
print("两数字相加的结果为:",a+b)
以上程序可以縮寫為:
#!/usr/bin/python
# -*- coding: utf-8 -*-
print("两数字相加的结果为:", float(input("请输入第 1 个数字:")) + float(input("请输入第 2 个数字:")))
整數對象可以按不同進制轉化為字符串對象。比如:
a = 10
print(bin(a)) #二进制, 输出:0b1010
print(oct(a)) #八进制, 输出:0o12
print(hex(a)) #十六进制,输出:0xa
我們也可以通過這樣的方式給整數賦值,比如:
a = 0b11 + 0o10 + 0xa
print(a) #3 + 8 + 10,输出21
之後在字符串章節,會介紹一些其它地有類似作用的方法。
int
函數在轉化字符串時,還可以輸入第二個參數。第二個參數表示進制,我們看以下示例:
a = int("10", 2) #2 进制,a的值为2
b = int("10", 3) #3 进制,b的值为3
c = int("10", 8) #8 进制,c的值为8
d = int("1A", 16) #16进制,d的值为26
e = int("z", 36) #36进制,e的值为35
print(a, b, c, d, e)
在這種方法下,可以支持2進制至36進制。在每一位中,0~9的數字可以用0
~9
表示,而10~35的數字可以用字母a
~z
表示(不區分大小寫)。這種方法下,不支持前綴的0b
、0o
和0x
。
除此之外,如果向第二個參數輸入0
,則會根據字符串前綴的0b
、0o
和0x
來判斷進制,我們看以下示例。
a = int("10", 0) #没有前缀,输出 10
b = int("0b10", 0) #二进制, 输出 2
c = int("0o10", 0) #八进制, 输出 8
d = int("0x10", 0) #十六进制,输出 16
print(a, b, c, d)
但是要注意,向第二個參數輸入0
的時候,輸入十進制數字時,字符串中第一個字符不能為"0"
。比如,以下的代碼會報錯:
print(int("10", 0)) #没有前缀,输出 10
print(int("010", 0)) #报错
初學者可以先跳過這一章節。待讀者參與到涉及數字精度的項目時,再進行查閱。
在 Python 中,只要電腦的可用內存足夠大,你就能表示足夠大的整數。這與許多其他語言是不同的。
※ 在 Python 2.x 的版本中並非如此,請注意。
我們在之前浮點數的帶餘除法中,已經注意到數字精度的問題。應輸出0.2
的,由於計算精度的原因,輸出為0.19999999999999996
。實際上,還有一個更簡單的數字精度的例子:
print(0.1 + 0.2) #输出为:0.30000000000000004
造成以上結果的原因,是計算機表示浮點數的方式導致的。計算機會用IEEE 754標準中的雙精度浮點數來表示 Python 中的浮點數,這種方法最多能保留二進制的53位有效數字。
對於一些在二進制中表示為無限循環小數的數字,比如十進制的0.1,在二進制下會表示為:0.0001100110011...,這不可避免地會產生截斷,最終存儲的數值只會是一個近似值。如果這些小誤差通過加法等方式累計,可以導致一些顯著的計算誤差。
一個通用的解決方法是round
函數。
round(number, n)
函數會將數字按十進制捨入至小數點後n
位。比如:
print(round(0.1 + 0.2, 2)) #输出为:0.3
我們可以估計程序所需要的最大精度,或者估計計算產生的最大誤差,來選擇捨入的位數。
還有一些其他方法可以用於減少這類誤差。比如有兩個函數可以對列表中的元素進行求和。我們通過[0.1] * 10
生成由10個0.1
組成的列表,然後代入這兩個函數中進行計算:
print(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1) #输出:0.9999999999999999
print(sum([0.1] * 10)) #输出:1.0
import math
print(math.fsum([0.1] * 10)) #输出:1.0
其中,math.fsum
函數精度一般更高,但耗時也更長。而sum
函數精度較低,但耗時較短。讀者可以根據自身情況進行選擇。
對於小數位數確定,且精度也確定的一些計算,比如貨幣的計算,可以使用整數來進行計算。比如,在加法程序中,如果我們要計算1000元+0.01元,可以用字符串的一些方法把"1000"
和"0.01"
分別處理為100000
和1
。相加之後為100001
,轉化為字符串後,再用字符串的方法加入小數點,輸出"1000.01"
。具體方法參見之後的字符串章節。
參見本教程第十八章節。建議初學者不要立刻去讀第十八章節的內容。至少是在學習完第十六章節後,再學習第十八章節。
位運算只對整數有意義。以下是所有位運算的方式:
a=44 #0010 1100
b=56 #0011 1000
print(a&b) #按位 与 运算符,若两数在该位都为1,则为1
#0010 1000 即40
print(a|b) #按位 或 运算符,在该位有至少一个数字1,则为1
#0011 1100 即60
print(a^b) #按位 异或 运算符,若两数在该位不同则为1
#0001 0100 即20
print(~a) #按位 取反 运算符,该数0与1互换
#由于整数表示的原理,这等同于 -a-1
print(a<<2) #该数左移2位,即与(2**2)相乘
#1011 0000 即176
print(a>>1) #该数右移1位,即除以(2**1)并向下取整
#0001 0110 即22
- ↑ type函數的Python文檔 https://docs.python.org/zh-cn/3.12/library/functions.html#type
- ↑ print函數的Python文檔 https://docs.python.org/zh-cn/3.12/library/functions.html#print