Python数字类型

作者:最西瓜 来源:《Core Python Programming, Second Edition》CH5. Numbers

在Python中数字是不可变的对象,每次改变值时都会创建一个新的对象。Python拥有多种数字:整数、长整型、布尔值、双精度浮点数、十进制浮点数(decimal)和复数。

请务必记住:在Python中所有变量都只是指向真正变量值的指针,而不是像C中那样是装有值的盒子。

复数

形如:64.375+8.55j -0.0224+0j 称之为复数,复数的实部和虚部都是浮点数,支持科学计数法。复数不是单纯的数字,而是拥有属性的类型。num.real是实部,num.imag是虚部,num.congugate()得到复数的共轭复数。

强制转换

当两个不同类型的数字进行互操作时,会将其中一方转换为另一方的类型。具体原则就是整数向浮点数转换,非复数向复数转换。可以调用coerce(a,b)函数将a b的类型统一,具体查看help(coerce)

Python支持真正的除法的原因在于Python是动态类型的,在执行除法时我们假设只能传入浮点数,但是用户可能传入整数。考虑如下代码:

1
2
def veloctiy(distance, totalTime):
    rate = distance / totalTime

如果只支持用传统除法,我们必须用如下代码绕过rate = float(distance) / float(totalTime)限制,在PEP238中有对此的详细描述。

取模运算作用于整数和浮点数,跟如下等式一致:x % y = x - math.floor(x/y) * y,作用于复数时只会对实部取模。

Python支持以下数字类型的工厂方法:bool(obj) int(obj, base=10) long(obj, base=10) float(obj) complex(str) complex(real, imag=0.0) 支持以下操作函数:

  • abs(num)对于复数则返回如下math.sqrt(num.real ** 2, num.imag ** 2)
  • divmod(num1, num2)以元组的形式同时返回商和余数,对于浮点数商返回math.floor(num1/num2) 对于复数商返回math.floor((num1/num2).real)
  • pow(num1, num2, mod=1)支持第三个参数,功能是先将num1做乘方运算num2再对mod取余;
  • round(flt, ndig=0) 对数字flt进行舍入,如果指定ndig,将舍入到指定小数点位数。舍入操作是向着远离0的方向进行的,这样round(.5)为1,round(-.5)为-1,而math.floor永远向着负数方向,以下代码验证:
1
2
3
4
5
6
import math
for eachNum in (.2, .7, 1.2, 1,7, -.2, -.7, -1.2, -1.7):
    print "int(%f)\t%f" % (eachNum, float(int(eachNum)))
    print "math.floor(%f)\t%f" % (eachNum, math.floor(eachNum))
    print "round(%f)\t%f" % (eachNum, round(eachNum))
    print "-------------------"

除了以上支持对所有数字的内置函数外,还有专用于整数的内置函数:

  • hex(num) oct(num) 专门用于返回16进制和8进制整数的字符串形式;
  • chr(num) ord(chr) 用于在字符和它的ASCII码之间进行转换;
  • unichr(num) 将Unicode码点转为Unicode字符串;

布尔值

需要重点讲一下布尔值,与Java不同的是Python中的布尔值其实是一种整数,在引入布尔类型之前,Python用1和0来表示真假。在算术环境下,True和False会被转为1和0。另外,True和Flase在Python中不是关键字,而是全局变量名,意味着可以交换它们的值。

1
2
3
True, False = False, True
bool(True)  #False
bool(False) #True

decimal

Python支持十进制浮点数的原因在于某些环境下需要完全精度,通过将小数部分和整数部分分开可以做到。十进制浮点数被实现在decimal模块中。十进制浮点数和双精度浮点数是不同的类型,不能混合使用。可以从整数、字符串和其它十进制浮点数构建浮点数,但是最好不要用双精度浮点数去构建,因为精度会出问题。代码如下:

1
2
3
4
5
from decimal import Decimal
dec = Decimal(.1)    #Decimal('0.1000000000000000055511151')
dec = Decimal('.1')  #Decimal('0.1')
# dec + 1.0  #Will produce Error
dec + Decimal('1.0') + 1  #Decimal('2.1')

random模块

介绍几个常用方法:

  • randint(a, b) 返回a <= N <= b之间的一个随机整数;
  • randrange(start, stop[, step])从range中返回一个随机整数;
  • uniform(a, b) 返回a <= N < b之间的一个随机浮点数;
  • random() 返回0.0 <= N < 1.0之间的一个随机浮点数;
  • choice(seq) 从非空序列seq中返回一个随机元素,如果seq是空的,将抛出IndexError错误;