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标准库---十一、内置类型:迭代器类型、序列类型
相关文章
相关标签/搜索