Python標準庫---十、內置類型:數字類型

上一篇文章: Python標準庫---九、內置類型:邏輯值檢測、布爾運算、比較
下一篇文章: Python標準庫---十一、內置類型:迭代器類型、序列類型

數字類型 --- int, float, complex

存在三種不一樣的數字類型: 整數, 浮點數 和 複數。 此外,布爾值屬於整數的子類型。 整數具備無限的精度。 浮點數一般使用 C 中的 double 來實現;有關你的程序運行所在機器上浮點數的精度和內部表示法可在 sys.float_info 中查看。 複數包含實部和虛部,分別以一個浮點數表示。 要從一個複數 z 中提取這兩個部分,可以使用 z.real 和 z.imag。 (標準庫包含附加的數字類型,如表示有理數的 fractions 以及以用戶定製精度表示浮點數的 decimal。)算法

數字是由數字字面值或內置函數與運算符的結果來建立的。 不帶修飾的整數字面值(包括十六進制、八進制和二進制數)會生成整數。 包含小數點或冪運算符的數字字面值會生成浮點數。 在數字字面值末尾加上 'j' 或 'J' 會生成虛數(實部爲零的複數),你能夠將其與整數或浮點數相加來獲得具備實部和虛部的複數。編程

Python 徹底支持混合算術:當一個二元運算符用於不一樣數字類型的操做數時,具備「較窄」 類型的操做數會被擴展爲另外一個操做數的類型,整數比浮點數更窄,浮點數又比複數更窄。 混合類型數字之間的比較也使用相同的規則。 構造器 int(), float() 和 complex() 可被用於生成特定類型的數字。segmentfault

全部數字類型(複數除外)都支持下列運算,按優先級升序排序(全部數字運算的優先級都高於比較運算):數組

evernotecid://D603D29C-DFBA-4C04-85E9-CCA3C33763F6/appyinxiangcom/23852268/ENResource/p19
clipboard.pngapp

註釋:編程語言

  1. 也稱爲整數除法。 結果值是一個整數,但結果的類型不必定是 int。 運算結果老是向負無窮的方向舍入: 1//2 爲 0, (-1)//2 爲 -1, 1//(-2) 爲 -1 而 (-1)//(-2) 爲 0。
  2. 不可用於複數。 而應在適當條件下使用 abs() 轉換爲浮點數。
  3. 從浮點數轉換爲整數會被舍入或是像在 C 語言中同樣被截斷;請參閱 math.floor() 和 math.ceil() 函數查看轉換的完整定義。
  4. float 也接受字符串 "nan" 和附帶可選前綴 "+" 或 "-" 的 "inf" 分別表示非數字 (NaN) 以及正或負無窮。
  5. Python 將 pow(0, 0) 和 0 ** 0 定義爲 1,這是編程語言的廣泛作法。
  6. 接受的數字字面值包括數碼 0 到 9 或任何等效的 Unicode 字符(具備 Nd 特徵屬性的代碼點)。
請參閱 http://www.unicode.org/Public... 查看具備 Nd 特徵屬性的代碼點的完整列表。

整數類型的按位運算

按位運算只對整數有意義。 計算按位運算的結果,就至關於使用無窮多個二進制符號位對二的補碼執行操做。函數

二進制按位運算的優先級全都低於數字運算,但又高於比較運算;一元運算 ~ 具備與其餘一元算術運算 (+ and -) 相同的優先級。ui

此表格是以優先級升序排序的按位運算列表:spa

clipboard.png

註釋:調試

  1. 負的移位數是非法的,會致使引起 ValueError。
  2. 左移 n 位等價於不帶溢出檢測地乘以 pow(2, n)。
  3. 右移 n 位等價於不帶溢出檢測地除以 pow(2, n)。
  4. 使用帶有至少一個額外符號擴展位的有限個二進制補碼錶示(有效位寬度爲 1 + max(x.bit_length(), y.bit_length()) 或以上)執行這些計算就足以得到至關於有無數個符號位時的一樣結果。

整數類型的附加方法

int 類型實現了 numbers.Integral abstract base class。 此外,它還提供了其餘幾個方法:

int.bit_length()

返回以二進制表示一個整數所須要的位數,不包括符號位和前面的零:

>>>
>>> n = -37
>>> bin(n)
'-0b100101'
>>> n.bit_length()
6

更準確地說,若是 x 非零,則 x.bit_length() 是使得 2(k-1) <= abs(x) < 2k 的惟一正整數 k。 一樣地,當 abs(x) 小到足以具備正確的舍入對數時,則 k = 1 + int(log(abs(x), 2))。 若是 x 爲零,則 x.bit_length() 返回 0。

等價於:

def bit_length(self):
    # binary representation:  bin(-37) --> '-0b100101'
    s = bin(self)      
    # remove leading zeros and minus sign
    s = s.lstrip('-0b') 
    # len('100101') --> 6
    return len(s)

3.1 新版功能.

int.to_bytes(length, byteorder, *, signed=False)

返回表示一個整數的字節數組。

>>> (1024).to_bytes(2, byteorder='big')
b'\x04\x00'
>>> (1024).to_bytes(10, byteorder='big')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00'
>>> (-1024).to_bytes(10, byteorder='big', signed=True)
b'\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00'
>>> x = 1000
>>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='little')
b'\xe8\x03'

整數會使用 length 個字節來表示。 若是整數不能用給定的字節數來表示則會引起 OverflowError。

byteorder 參數肯定用於表示整數的字節順序。 若是 byteorder 爲 "big",則最高位字節放在字節數組的開頭。 若是 byteorder 爲 "little",則最高位字節放在字節數組的末尾。 要請求主機系統上的原生字節順序,請使用 sys.byteorder 做爲字節順序值。

signed 參數肯定是否使用二的補碼來表示整數。 若是 signed 爲 False 而且給出的是負整數,則會引起 OverflowError。 signed 的默認值爲 False。

3.2 新版功能.

classmethod int.from_bytes(bytes, byteorder, *, signed=False)

返回由給定字節數組所表示的整數。

>>> int.from_bytes(b'\x00\x10', byteorder='big')
16
>>> int.from_bytes(b'\x00\x10', byteorder='little')
4096
>>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=True)
-1024
>>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=False)
64512
>>> int.from_bytes([255, 0, 0], byteorder='big')
16711680

bytes 參數必須爲一個 bytes-like object 或是生成字節的可迭代對象。

byteorder 參數肯定用於表示整數的字節順序。 若是 byteorder 爲 "big",則最高位字節放在字節數組的開頭。 若是 byteorder 爲 "little",則最高位字節放在字節數組的末尾。 要請求主機系統上的原生字節順序,請使用 sys.byteorder 做爲字節順序值。

signed 參數指明是否使用二的補碼來表示整數。

3.2 新版功能.

浮點類型的附加方法

float 類型實現了 numbers.Real abstract base class。 float 還具備如下附加方法。

float.as_integer_ratio()

返回一對整數,其比率正好等於原浮點數而且分母爲正數。 無窮大會引起 OverflowError 而 NaN 則會引起 ValueError。

float.is_integer()

若是 float 實例可用有限位整數表示則返回 True,不然返回 False:

>>>
>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False

兩個方法均支持與十六進制數字符串之間的轉換。 因爲 Python 浮點數在內部存儲爲二進制數,所以浮點數與 十進制數 字符串之間的轉換每每會致使微小的舍入錯誤。 而十六進制數字符串卻容許精確地表示和描述浮點數。 這在進行調試和數值工做時很是有用。

float.hex()

以十六進制字符串的形式返回一個浮點數表示。 對於有限浮點數,這種表示法將老是包含前導的 0x 和尾隨的 p 加指數。

classmethod float.fromhex(s)

返回以十六進制字符串 s 表示的浮點數的類方法。 字符串 s 能夠帶有前導和尾隨的空格。

請注意 float.hex() 是實例方法,而 float.fromhex() 是類方法。

十六進制字符串採用的形式爲:

[sign] ['0x'] integer ['.' fraction] ['p' exponent]

可選的 sign 能夠是 + 或 -,integer 和 fraction 是十六進制數碼組成的字符串,exponent 是帶有可選前導符的十進制整數。 大小寫沒有影響,在 integer 或 fraction 中必須至少有一個十六進制數碼。 此語法相似於 C99 標準的 6.4.4.2 小節中所描述的語法,也是 Java 1.5 以上所使用的語法。 特別地,float.hex() 的輸出能夠用做 C 或 Java 代碼中的十六進制浮點數字面值,而由 C 的 %a 格式字符或 Java 的 Double.toHexString 所生成的十六進制數字符串由爲 float.fromhex() 所接受。

請注意 exponent 是十進制數而非十六進制數,它給出要與係數相乘的 2 的冪次。 例如,十六進制數字符串 0x3.a7p10 表示浮點數 (3 + 10./16 + 7./162) * 2.010 即 3740.0:

>>>
>>> float.fromhex('0x3.a7p10')
3740.0

對 3740.0 應用反向轉換會獲得另外一個表明相同數值的十六進制數字符串:

>>>
>>> float.hex(3740.0)
'0x1.d380000000000p+11'

數字類型的哈希運算

對於可能爲不一樣類型的數字 x 和 y,要求 x == y 時一定 hash(x) == hash(y) (詳情參見 __hash__() 方法的文檔)。 爲了便於在各類數字類型 (包括 int, float, decimal.Decimal 和 fractions.Fraction) 上實現並保證效率,Python 對數字類型的哈希運算是基於爲任意有理數定義統一的數學函數,所以該運算對 int 和 fractions.Fraction 的所有實例,以及 float 和 decimal.Decimal 的所有有限實例都可用。 從本質上說,此函數是經過以一個固定質數 P 進行 P 降模給出的。 P 的值在 Python 中能夠 sys.hash_info 的 modulus 屬性的形式被訪問。

CPython implementation detail: 目前所用的質數設定,在 C long 爲 32 位的機器上 P = 231 - 1 而在 C long 爲 64 位的機器上 P = 261 - 1。

詳細規則以下所述:

  • 若是 x = m / n 是一個非負的有理數且 n 不可被 P 整除,則定義 hash(x) 爲 m * invmod(n, P) % P,其中 invmod(n, P) 是對 n 模 P 取反。
  • 若是 x = m / n 是一個非負的有理數且 n 可被 P 整除(但 m 不能)則 n 不能對 P 降模,以上規則不適用;在此狀況下則定義 hash(x) 爲常數值 sys.hash_info.inf。
  • 若是 x = m / n 是一個負的有理數則定義 hash(x) 爲 -hash(-x)。 若是結果哈希值爲 -1 則將其替換爲 -2。
  • 特定值 sys.hash_info.inf, -sys.hash_info.inf 和 sys.hash_info.nan 被用做正無窮、負無窮和空值(所分別對應的)哈希值。 (全部可哈希的空值都具備相同的哈希值。)
  • 對於一個 complex 值 z,會經過計算 hash(z.real) + sys.hash_info.imag hash(z.imag) 將實部和虛部的哈希值結合起來,並進行降模 2sys.hash_info.width 以使其處於 range(-2(sys.hash_info.width - 1), 2*(sys.hash_info.width - 1)) 範圍以內。 一樣地,若是結果爲 -1 則將其替換爲 -2。

爲了闡明上述規則,這裏有一些等價於內置哈希算法的 Python 代碼示例,可用於計算有理數、float 或 complex 的哈希值:

import sys, math

def hash_fraction(m, n):
    """Compute the hash of a rational number m / n.

    Assumes m and n are integers, with n positive.
    Equivalent to hash(fractions.Fraction(m, n)).

    """
    P = sys.hash_info.modulus
    # Remove common factors of P.  (Unnecessary if m and n already coprime.)
    while m % P == n % P == 0:
        m, n = m // P, n // P

    if n % P == 0:
        hash_value = sys.hash_info.inf
    else:
        # Fermat's Little Theorem: pow(n, P-1, P) is 1, so
        # pow(n, P-2, P) gives the inverse of n modulo P.
        hash_value = (abs(m) % P) * pow(n, P - 2, P) % P
    if m < 0:
        hash_value = -hash_value
    if hash_value == -1:
        hash_value = -2
    return hash_value

def hash_float(x):
    """Compute the hash of a float x."""

    if math.isnan(x):
        return sys.hash_info.nan
    elif math.isinf(x):
        return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
    else:
        return hash_fraction(*x.as_integer_ratio())

def hash_complex(z):
    """Compute the hash of a complex number z."""

    hash_value = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag)
    # do a signed reduction modulo 2**sys.hash_info.width
    M = 2**(sys.hash_info.width - 1)
    hash_value = (hash_value & (M - 1)) - (hash_value & M)
    if hash_value == -1:
        hash_value = -2
    return hash_value
上一篇文章: Python標準庫---九、內置類型:邏輯值檢測、布爾運算、比較
下一篇文章: Python標準庫---十一、內置類型:迭代器類型、序列類型
相關文章
相關標籤/搜索