上一篇文章:Python标准库---9、内置类型:逻辑值检测、布尔运算、比较
下一篇文章:Python标准库---11、内置类型:迭代器类型、序列类型
数字类型 --- int, float, complex
存在三种不同的数字类型: 整数, 浮点数 和 复数。 此外,布尔值属于整数的子类型。 整数具有无限的精度。 浮点数通常使用 C 中的 double 来实现;有关你的程序运行所在机器上浮点数的精度和内部表示法可在 sys.float_info 中查看。 复数包含实部和虚部,分别以一个浮点数表示。 要从一个复数 z 中提取这两个部分,可使用 z.real 和 z.imag。 (标准库包含附加的数字类型,如表示有理数的 fractions 以及以用户定制精度表示浮点数的 decimal。)
数字是由数字字面值或内置函数与运算符的结果来创建的。 不带修饰的整数字面值(包括十六进制、八进制和二进制数)会生成整数。 包含小数点或幂运算符的数字字面值会生成浮点数。 在数字字面值末尾加上 'j' 或 'J' 会生成虚数(实部为零的复数),你可以将其与整数或浮点数相加来得到具有实部和虚部的复数。
Python 完全支持混合算术:当一个二元运算符用于不同数字类型的操作数时,具有“较窄” 类型的操作数会被扩展为另一个操作数的类型,整数比浮点数更窄,浮点数又比复数更窄。 混合类型数字之间的比较也使用相同的规则。 构造器 int(), float() 和 complex() 可被用于生成特定类型的数字。
所有数字类型(复数除外)都支持下列运算,按优先级升序排序(所有数字运算的优先级都高于比较运算):
evernotecid://D603D29C-DFBA-4C04-85E9-CCA3C33763F6/appyinxiangcom/23852268/ENResource/p19
注释:
- 也称为整数除法。 结果值是一个整数,但结果的类型不一定是 int。 运算结果总是向负无穷的方向舍入: 1//2 为 0, (-1)//2 为 -1, 1//(-2) 为 -1 而 (-1)//(-2) 为 0。
- 不可用于复数。 而应在适当条件下使用 abs() 转换为浮点数。
- 从浮点数转换为整数会被舍入或是像在 C 语言中一样被截断;请参阅 math.floor() 和 math.ceil() 函数查看转换的完整定义。
- float 也接受字符串 "nan" 和附带可选前缀 "+" 或 "-" 的 "inf" 分别表示非数字 (NaN) 以及正或负无穷。
- Python 将 pow(0, 0) 和 0 ** 0 定义为 1,这是编程语言的普遍做法。
- 接受的数字字面值包括数码 0 到 9 或任何等效的 Unicode 字符(具有 Nd 特征属性的代码点)。
请参阅 http://www.unicode.org/Public... 查看具有 Nd 特征属性的代码点的完整列表。
整数类型的按位运算
按位运算只对整数有意义。 计算按位运算的结果,就相当于使用无穷多个二进制符号位对二的补码执行操作。
二进制按位运算的优先级全都低于数字运算,但又高于比较运算;一元运算 ~ 具有与其他一元算术运算 (+ and -) 相同的优先级。
此表格是以优先级升序排序的按位运算列表:
注释:
- 负的移位数是非法的,会导致引发 ValueError。
- 左移 n 位等价于不带溢出检测地乘以 pow(2, n)。
- 右移 n 位等价于不带溢出检测地除以 pow(2, n)。
- 使用带有至少一个额外符号扩展位的有限个二进制补码表示(有效位宽度为 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, mathdef 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_valuedef 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标准库---9、内置类型:逻辑值检测、布尔运算、比较
下一篇文章:Python标准库---11、内置类型:迭代器类型、序列类型