使用者: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'>

計算結果的類型[編輯 | 編輯原始碼]

Python 在進行計算時,會先將所有數字轉化成可能需要的、最「通用」的類型。浮點數比整數通用,複數比浮點數通用。比如:

  1. 當整數和整數進行計算時,結果一般是兩者之間最通用的類型:整數;
  2. 當整數和浮點數進行計算時,結果一定是兩者之間最通用的類型:浮點數;
  3. 當整數和複數進行計算時,結果一定是兩者之間最通用的類型:複數。

以上內容只有兩個例外,就是:

  1. 整數和整數之間的除法一定會返回浮點數。
  2. 整數的負整數次冪會返回浮點數。

除法[編輯 | 編輯原始碼]

擴展(選學)
這與許多其他語言不一致。有些程式語言在遇到除數為零時會返回「無窮大」或「NaN」。但和其他語言一樣, Python 的浮點數也提供了無窮大和NaN。

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

無窮大與NaN(選學)[編輯 | 編輯原始碼]

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")等方式也是可以的。

除一般的計算之外。無窮大的運算遵循以下法則:

  1. 無窮大和零作乘法,結果為NaN。
  2. 正無窮大和負無窮大作加法,結果為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, y)[編輯 | 編輯原始碼]

此函數也會返回一類帶餘除法的餘數。

% 運算符不同,math.fmod 返回的餘數、和被除數 x 的符號相同。

在被除數遠小於除數時,這種方法的精度比 % 運算要高。因為:

import math
print(math.fmod(-1e-100,1e100))  #结果为:-1e-100
print(-1e-100 % 1e100)        #结果为:1e100-1e-100,并舍入为:1e100

所以,作浮點數帶餘除法時,更推薦使用 math.fmod 而不是 %

math.remainder(x, y)[編輯 | 編輯原始碼]

此函數也會返回一類不同的帶餘除法的餘數。

與上述的兩種運算不同,這種方法對商有規定:它會將 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)

math模塊[編輯 | 編輯原始碼]

除以上運算符之外,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 提供了幾種簡單的函數,可以利用已有對象,創建對應的的數字對象。

創建整數對象[編輯 | 編輯原始碼]

提示
在對應Python文檔中,有形如「如果 x 定義了 __int__()」的描述。該部分內容及類似內容的詳細解釋,將在之後的類與Python的運算中講解。

函數int可以將內容轉化為整數。比如:

print(int(1.23))      #结果:1
print(int(-1.23))     #结果:-1
print(int(" 1023")+1) #结果:1024
print(int(1))         #结果:1

int函數可以將浮點數或字符串轉化為整數。如果把字符串轉化為整數,被轉化的字符串主要部分只能包含09以及+-,位於主要部分前後的空格和換行符\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函數[編輯 | 編輯原始碼]

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表示(不區分大小寫)。這種方法下,不支持前綴的0b0o0x

除此之外,如果向第二個參數輸入0,則會根據字符串前綴的0b0o0x來判斷進位,我們看以下示例。

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 中的浮點數,這種方法最多能保留二進位的52位有效數字。

對於一些在二進位中表示為無限循環小數的數字,比如十進位的0.1,在二進位下會表示為:0.0001100110011...,這不可避免地會產生截斷,最終存儲的數值只會是一個近似值。如果這些小誤差通過加法等方式累計,可以導致一些顯著的計算誤差。

縮小或解決誤差[編輯 | 編輯原始碼]

round 函數[編輯 | 編輯原始碼]

一個通用的解決方法是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"分別處理為1000001。相加之後為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

參考文獻[編輯 | 編輯原始碼]