python浓缩(5)数字

大兔子大兔子 提交于 2019-12-09 14:15:13

详细介绍每一种数字类型,适用的各种运算符, 及用于处理数字的内建函数。

5.1 数字类型

数字提供了标量贮存和直接访问。它是不可更改类型,也就是说变更数字的值会生成新的对象。

Python 支持多种数字类型:整型、长整型、布尔型、双精度浮点型、十进制浮点型和复数。

如何创建数值对象并用其赋值

anInt = 1

如何更新数字对象

通过给数字对象(重新)赋值, 您可以“更新”一个数值对象。实际上你并没有更新该对象的原始数值。因为数值对象是不可改变对象。Python的对象模型与常规对象模型有些不同。更新实际上是生成了一个新的数值对象,并得到它的引用。

在Python 中, 变量更像一个指针指向装变量值的盒子。 对不可改变类型来说, 你无法改变盒子的内容, 但你可以将指针指向一个新盒子。每次将另外的数字赋给变量的时候,实际上创建了一个新的对象并把它赋给变量.(不仅仅是数字,对于所有的不可变类型,都是这么回事)

如何删除数字对象

你无法真正删除一个数值对象, 你仅仅是不再使用它而已。如果你实际上想删除一个数值对象的引用, 使用 del 语句(参见3.5.6 小节)。如果试图使用一个已经被删除的对象引用, 会引发NameError 异常。

del anInt
del aLong, aFloat, aComplex

5.2 整型

Python 有几种整数类型。布尔类型是只有两个值的整型。常规整型是绝大多数现代系统都能识别的整型。Python 也有长整数类型。然而,它表示的数值大小远超过C 语言的长整数 。

5.2.1 布尔型

该类型的取值范围只有两个值,布尔值True和布尔值False。

5.2.2 标准整数类型

Python 的标准整数类型是最通用的数字类型。

在大多数32 位机器上,标准整数类型的取值范围是-231 到231-1,也就是-2,147,483,648 到 2,147,483,647;

如果在 64 位机器上使用 64 位编译器编译Python,那么在这个系统上的整数将是64 位;

下面是一些Python 标准整数类型对象的例子:0101 84 -237 0x80 017 -680 -0X92

Python 标准整数类型等价于C 的(有符号)长整型。整数一般以十进制表示,但是Python也支持八进制或十六进制来表示整数。如果八进制整数以数字“0”开始, 十六进制整数则以“0x” 或“0X” 开始。

5.2.3 长整型

不要将python的长整型和C 或其它编译型语言的长整数类型混淆。那些语言的长整数典型的取值范围是32 或64 位。Python 的长整数类型能表达的数值仅仅与你的机器支持的(虚拟)内存大小有关, 既Python 能轻松表达很大很大很大的整数。

长整数类型是标准整数类型的超集, 当你的程序需要使用比标准整数类型更大的整数时,长整数类型就有用武之地了。在一个整数值后面加个L(大写或小写都可以),表示这个整数是长整数。这个整数可以是十进制,八进制, 或十六进制。下面是一些长整数的例子:

16384L -0x4E8L 017L -2147483648l 052144364L
299792458l 0xDECADEDEADBEEFBADFEEDDEAL -5432101234L

核心风格:用大写字母 “L”表示长整数

目前整型和长整型正在逐渐缓慢的统一,您只有在对长整数调用repr()函数时才有机会看到“L”,如果对长整数对象调用str()函数就看不到 L 。举例如下:

>>> aLong = 999999999l
>>> aLong
999999999L
>>> print aLong
999999999

5.2.4 整型和长整型的统一

这两种整数类型正在逐渐统一为一种。

Python 2.1
>>> 9999 ** 8
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OverflowError: integer exponentiation
Python 2.2
>>> 9999 ** 8
99920027994400699944002799920001L

移除这个错误是第一步。 下一步修改位移位; 左移比特导致出界(导致0 值)在过去是经常可能发生的事;

>>> 2 << 32
0

在Python2.3 中, 这个操作产生一个警告, 不过在2.4 版里移除了这个 Warning, 并且这步操作生成了一个真正的长整数。

Python 2.3
>>> 2 << 32
__main__:1: FutureWarning: x<<y losing bits or changing sign will return a long
in Python 2.4
and up
0
Python 2.4
>>> 2 << 32
8589934592L

不远的将来,至少普通用户会几乎感觉不到长整型的存在。必要时整型会悄悄自动转换为长整型。当然,那些要调用C 的人仍然可以继续使用这两种整数类型, 因为C 代码必须区分不同的整数类型。

如果你想详细了解标准整型与长整型整合的信息,请阅读PEP237.

5.3 双精度浮点数

Python 中的浮点数类似C 语言中的double 类型, 是双精度浮点数,可以用直接的十进制或科学计数法表示。每个浮点数占8 个字节(64 比特),完全遵守IEEE754 号规范(52M/11E/1S),其中52 个比特用于表示底,11 个比特用于表示指数(可表示的范围大约是正负10 的308.25次方), 剩下的一个比特表示符号。这看上去相当完美,然而,实际精度依赖于机器架构和创建Python 解释器的编译器。

浮点数值通常都有一个小数点和一个可选的后缀e(大写或小写,表示科学计数法)。在e和指数之间可以用正(+)或负(-)表示指数的正负(正数的话可以省略符号)。下面是一些典型的浮点数值的例子:

0.0 -777. 1.6 -5.555567119 96e3 * 1.0
4.3e25 9.384e-23 -2.172818 float(12) 1.000000001
3.1416 4.2E-10 -90. 6.022e23 -1.609E-19

5.4 复数

在很久以前,数学家们被下面这样的等式困扰。

x2 = -1

一个实数和一个虚数的组合构成一个复数。一个复数是一对有序浮点数(x, y)。表示为 x + yj, 其中x 是实数部分,y 是虚数部分。

下面是Python 语言中有关复数的几个概念:

􀁺 虚数不能单独存在,它们总是和一个值为 0.0 的实数部分一起来构成一个复数。

􀁺 复数由实数部分和虚数部分构成

􀁺 表示虚数的语法: real+imagj

􀁺 实数部分和虚数部分都是浮点数

􀁺 虚数部分必须有后缀j 或J。

下面是一些复数的例子:

64.375+1j 4.23-8.5j 0.23-8.55j 1.23e-045+6.7e+089j
6.23+1.5j -1.23-875J 0+1j 9.80665-8.31441J -.0224+0j

5.4.1 复数的内建属性

复数对象拥有数据属性, 分别为该复数的实部和虚部。复数还拥有conjugate 方法, 调用它可以返回该复数的共轭复数对象。

  • num.real 该复数的实部

  • num num.imag 该复数的虚部

  • num.conjugate() 返回该复数的共轭复数

>>> aComplex = -8.333-1.47j
>>> aComplex
(-8.333-1.47j)
>>> aComplex.real
-8.333
>>> aComplex.imag
-1.47
>>> aComplex.conjugate()
(-8.333+1.47j)

5.5 运算符

数值类型可进行多种运算。从标准运算符到数值运算符,甚至还有专门的整数运算符。

5.5.1 混合模式运算符

当两个整数相加时, + 号表示整数加法, 当两个浮点数相加时, + 表示浮点数加法, 依此类推。在Python 中, 甚至非数字类型也可以使用 + 运算符。举例来说, 字符串A + 字符串B 并不表示加法操作, 它表示的是把这两个字符串连接起来, 生成一个新的字符串。 这也体现了重载概念的具体应用。

Python 支持不同的数字类型相加。当一个整数和一个浮点数相加时, 系统会决定使用整数加法还是浮点数加法(实际上并不存在混合运算)。Python 使用数字类型强制转换的方法来解决数字类型不一致。这种操作不是随意进行的, 它遵循以下基本规则:当两个操作数类型不一致时, Python 去检查一个操作数是否可以转换为另一类型的操作数。如果可以,转换它并返回转换结果。由于某些转换是不可能的,比如果将一个复数转换为非复数类型, 将一个浮点数转换为整数等等,因此转换过程必须遵守几个规则。

要将一个整数转换为浮点数,只要在整数后面加个 .0 就可以了。 要将一个非复数转换为复数,则只需要要加上一个 “0j” 的虚数部分。这些类型转换的基本原则是: 整数转换为浮点数, 非复数转换为复数。 在Python 语言这样描述coerce() 方法:

􀁺 如果有一个操作数是复数, 另一个操作数被转换为复数。

􀁺 否则,如果有一个操作数是浮点数, 另一个操作数被转换为浮点数。

􀁺 否则, 如果有一个操作数是长整数,则另一个操作数被转换为长整数;

􀁺 否则,两者必然都是普通整数,无须类型转换。

不过在确实需要明确指定对某种数据类型进行特殊类型转换的场合,Python 提供了 coerce() 内建函数来帮助你实现这种转换。

5.5.2 标准类型运算符

上文中提到的混合模式运算, 在运算之前,Python 内部会将两个操作数转换为同一数据类型。

下面是一些数字标准运算的例子:

>>> 5.2 == 5.2
True
>>> -719 >= 833
False
>>> 5+4e >= 2-3e
True
>>> 2 < 5 < 9 # same as ( 2 < 5 ) and ( 5 < 9 )
True
>>> 77 > 66 == 66 # same as ( 77 > 66 ) and ( 66 == 66 )
True
>>> 0. < -90.4 < 55.3e2 != 3 < 181
False
>>> (-1 < 1) or (1 < -1)
True

5.5.3 算术运算符

Python 支持单目运算符正号(+)和负号(-), 双目运算符, +,-,*,/,%,还有 ** ,分别表示加法,减法, 乘法, 除法, 取余, 和幂运算。整除运算符 // 。

除法

  • 对整数操作数,会执行“地板除”(floor,取比商小的最大整数);

  • 对浮点操作数会执行真正的除法;

在未来的Python 版本中,/ 的行为将变更为真正的除法, 会增加一种新的运算来表示地板除。

下面我们总结一下Python 现在的除法规则, 以及未来的除法规则:

传统除法

如果是整数除法, 传统除法会舍去小数部分,返回一个整数(地板除)。如果操作数之一是浮点数,则执行真正的除法。

真正的除法

除法运算总是返回真实的商, 不管操作数是整数还是浮点数。在未来版本的Python 中,这将是除法运算的标准行为。现阶段通过执行 from __future__ import division 指令:

>>> from __future__ import division
>>> 1 / 2 # returns real quotient
0.5
>>> 1.0 / 2.0 # returns real quotient
0.5

地板除

一个新的运算符 // 已经被增加进来, 以执行地板除: // 除法不管操作数何种数值类型,总是舍去小数部分,返回数字序列中比真正的商小的最接近的数字。

>>> 1 // 2 # floors result, returns integer # 地板除, 返回整数
0
>>> 1.0 // 2.0 # floors result, returns float # 地板除, 返回浮点数
0.0
>>> -1 // 2 # move left on number line# 返回比 –0.5 小的整数, 也就是 -1
-1
def velocity(distance, totalTime):
    rate = distance / totalTime

你可能会说, 只要有一个参数为浮点数这个函数就能正常工作。像上面提到的那样,要确保它能正常工作需要强制将参数转换为浮点类型, 也就是 rate = float(distance) / float(totalTime)。将来除法将变更为真正的除法,上面的代码可以无需更改正常工作。需要地板除的地方只需要改变为两个连续的除号。

是的, 代码会受到一些影响, Python 团队已经创作了一系列脚本帮助你转换旧代码,以确保它能适应新的除法行为。而且对那些强烈需要某种除法行为的人来说, Python 解释器提供了 Qdivision_style 启动参数。 -Qnew 执行新的除法行为, -Qold 则执行传统除法行为(默认为Qold)。你也可以帮助你的用户使用-Qwarn 或 –Qwarnall 参数度过过渡时期。

表5.2 总结了除法运算符在不同Python 版本中的行为差异。

取余

整数取余相当容易理解, 浮点数取余就略复杂些。对于复数,取余的定义类似于浮点数,不同之处在于商仅取其实数部分,即:x - (math.floor((x/y).real) * y)

幂运算

幂运算操作符和一元操作符之间的优先级关系比较特别: 幂运算操作符比其左侧操作数的一元操作符优先级低,比起右侧操作数的一元操作符的优先级高,由于这个特性你会在算术运算符表中找到两个** .eg:

>>> 3 ** 2
9
>>> -3 ** 2 # ** 优先级高于左侧的 -
-9
>>> (-3) ** 2 # 加括号提高 -的优先级
9
>>> 4.0 ** -1.0 # ** 优先级低于右侧的 -
0.25

第2 种情况下解释器先计算 3**2 再取其相反数,我们需要给"-3"加上括号来得到我们希望的结果。最后一个例子,结果是4**(-1),这是按照规定的优先级获得的结果.

>>> 4 ** -1
Traceback (innermost last):
File "<stdin>", line 1, in ?
ValueError: integer to the negative power

总结

表5.3 总结了所有的算术运算符, 从上到下, 计算优先级依次降低。 这里列出的所有

运算符都比即将在5.5.4 小节讲到的位运算符优先级高。

下面是更多Python 数值运算的例子:

>>> -442 - 77
-519
>>>
>>> 4 ** 3
64
>>>
>>> 4.2 ** 3.2
98.7183139527
>>> 8 / 3
2
>>> 8.0 / 3.0
2.66666666667
>>> 8 % 3
2
>>> (60. - 32.) * ( 5. / 9. )
15.5555555556
>>> 14 * 0x04
56
>>> 0170 / 4
30
>>> 0x80 + 0777
639
>>> 45L * 22L
990L
>>> 16399L + 0xA94E8L
709879L
>>> -2147483648L - 52147483648L
-54294967296L
>>> 64.375+1j + 4.23-8.5j
(68.605-7.5j)
>>> 0+1j ** 2 # same as 0+(lj**2)
(-1+0j)
>>> 1+1j ** 2 # same as 1+(lj**2)
0j
>>> (1+1j) ** 2
2j

注意指数运算符的优先级高于连接实部和虚部的+号运算符。就上面最后一个例子来说, 我们人为的加上了括号,这就改变运算顺序, 从而得到我们想要的结果。

5.5.4 *位运算符(只适用于整数)

Python 整数支持标准位运算:取反(~),按位 与(&), 或(|) 及 异或(^) 及左移(<<)和右移(>>)。Python 这样处理位运算:

􀁺 负数会被当成正数的 2 进制补码处理。

􀁺 左移和右移 N 位等同于无溢出检查的2 的N 次幂运算: 2**N。

􀁺 对长整数来说, 位运算符使用一种经修改的 2 进制补码形式,使得符号位可以无限的向左扩展。

取反(~)运算的优先级与数字单目运算符相同, 是所有位操作符中优先级最高的一个。 左移和右移运算的优先级次之,但低于加减法运算。与, 或, 异或 运算优先级最低。所有位运算符按优先级高低列在表 5.4 中。

表5.4 整型位运算符

位运算符 功能

~num 单目运算,对数的每一位取反。结果为

num1 << num2 Num1 左移 num2 位

num1 >> num2 Num1 右移 num2 位

num1 & num2 num1 与 num2 按位与

num1 ^ num2 num1 异或 num2

num1 | num2 num1 与 num2 按位或

下面是几个使用整数30(011110),45(101101),60(111100)进行位运算的例子:

>>> 30 & 45
12
>>> 30 | 45
63
>>> 45 & 60
44
>>> 45 | 60
61
>>> ~30
-31
>>> ~45
-46
>>> 45 << 1
90
>>> 60 >> 2
15
>>> 30 ^ 45
51

5.6 内建函数与工厂函数

5.6.1 标准类型函数

在上一章中, 我们介绍了 cmp(), str() 和 type() 内建函数。 这些函数可以用于所有的标准类型。

>>> cmp(-6, 2)
-1
>>> cmp(-4.333333, -2.718281828)
-1
>>> cmp(0xFF, 255)
0
>>> str(0xFF)
'255'
>>> str(55.3e2)
'5530.0'
>>> type(0xFF)
<type 'int'>
>>> type(98765432109876543210L)
<type 'long'>
>>> type(2-1j)
<type 'complex'>

5.6.2 数字类型函数

转换工厂函数

函数 int(), long(), float() 和 complex() 用来将其它数值类型转换为相应的数值类型

  • 从Python1.5 版本开始, 这些函数也接受字符串参数, 返回字符串所表示的数值;

  • 从Python1.6 版开始,int() 和 long() 在转换字符串时,接受一个进制参数,如果是数字类型之间的转换,则这个进制参数不能使用;

  • 从Python2.2 起, 有了第五个内建函数 bool()。它用来将整数值1 和0 转换为标准布尔值 True 和False.

由于Python 2.2 对类型和类进行了整合(这里指Python 的传统风格类和新风格类), 所有这些内建函数现在都转变为工厂函数。所谓工厂函数就是指这些内建函数都是类对象, 当你调用它们时,实际上是创建了一个类实例。eg:

>>> int(4.25555)
4
>>> long(42)
42L
>>> float(4)
4.0
>>> complex(4)
(4+0j)
>>> complex(2.4, -8)
(2.4-8j)
>>> complex(2.3e-10, 45.3e4)
(2.3e-10+453000j)

表5.5 数值工厂函数总结

功能函数

Python 有五个运算内建函数用于数值运算: abs(), coerce(), divmod(), pow(), pow()和 round()。

abs()

abs()返回给定参数的绝对值。如果参数是一个复数, 那么就返回math.sqrt(num.real2 +num.imag2)。下面是几个abs()函数的示例:

>>> abs(-1)
1
>>> abs(10.)
10.0
>>> abs(1.2-2.1j)
2.41867732449
>>> abs(0.23 - 0.78)
0.55

coerce()

尽管从技术上讲它是一个数据类型转换函数,不过它的行为更像一个运算符。函数coerce()为程序员提供了不依赖Python 解释器, 而是自定义两个数值类型转换的方法。

对一种新创建的数值类型来说, 这个特性非常有用。函数coerce一个包含类型转换完毕的两个数值元素的元组。下面是几个例子:

>>> coerce(1, 2)
(1, 2)
>>> coerce(1.3, 134L)
(1.3, 134.0)
>>>
>>> coerce(1, 134L)
(1L, 134L)
>>>
>>> coerce(1j, 134L)
(1j, (134+0j))
>>>
>>> coerce(1.23-41j, 134L)
((1.23-41j), (134+0j))

divmod()

divmod()内建函数把除法和取余运算结合起来, 返回一个包含商和余数的元组。

对整数来说, 它的返回值就是地板除和取余操作的结果;

对浮点数来说, 返回的商部分是math.floor(num1/num2);

对复数来说, 商部分是ath.floor((num1/num2).real);

>>> divmod(10,3)
(3, 1)
>>> divmod(3,10)
(0, 3)
>>> divmod(10,2.5)
(4.0, 0.0)
>>> divmod(2.5,10)
(0.0, 2.5)
>>> divmod(2+1j, 0.5-1j)
(0j, (2+1j))

pow()

函数 pow() 和双星号 (**) 运算符都可以进行指数运算。不过二者的区别并不仅仅在于一个是运算符,一个是内建函数。

内建函数pow()还接受第三个可选的参数,一个余数参数。如果有这个参数的, pow() 先进行指数运算,然后将运算结果和第三个参数进行取余运算。这个特性主要用于密码运算,并且比 pow(x,y) % z 性能更好, 这是因为这个函数的实现类似于C 函数 pow(x,y,z)。

>>> pow(2,5)
32
>>>
>>> pow(5,2)
25
>>> pow(3.141592,2)
9.86960029446
>>>
>>> pow(1+1j, 3)
(-2+2j)

round()

内建函数round()用于对浮点数进行四舍五入运算。它有一个可选的小数位数参数。如果不提供小数位参数, 它返回与第一个参数最接近的整数(但仍然是浮点类型)。第二个参数告诉round 函数将结果精确到小数点后指定位数。

>>> round(3)
3.0
>>> round(3.45)
3.0
>>> round(3.4999999)
3.0
>>> round(3.4999999, 1)
3.5
>>> import math
>>> for eachNum in range(10):
... print round(math.pi, eachNum)
...
3.0
3.1
3.14
3.142
3.1416
3.14159
3.141593
3.1415927
3.14159265
3.141592654
3.1415926536
>>> round(-3.5)
-4.0
>>> round(-3.4)
-3.0
>>> round(-3.49)
-3.0
>>> round(-3.49, 1)
-3.5

值得注意的是 round() 函数是按四舍五入的规则进行取整。也就是round(0.5)得到1,round(-0.5)得到-1。猛一看 int(), round(), math.floor() 这几个函数好像做的是同一件事, 下面列出它们之间的不同之处:

  • 函数 int()直接截去小数部分。(返回值为整数)

  • 函数 floor()得到最接近原数但小于原数的整数。(返回值为浮点数)

  • 函数 round()得到最接近原数的整数。(返回值为浮点数)

如下例子用四个正数和四个负数作为这三个函数的参数,将返回结果列在一起做个比较:

>>> import math
>>> for eachNum in (.2, .7, 1.2, 1.7, -.2, -.7, -1.2, -1.7):
... print "int(%.1f)\t%+.1f" % (eachNum, float(int(each-
Num)))
... print "floor(%.1f)\t%+.1f" % (eachNum,
... math.floor(eachNum))
... print "round(%.1f)\t%+.1f" % (eachNum, round(eachNum))
... print '-' * 20
...
int(0.2) +0.0
floor(0.2) +0.0
round(0.2) +0.0
--------------------
int(0.7) +0.0
floor(0.7) +0.0
round(0.7) +1.0
--------------------
int(1.2) +1.0
floor(1.2) +1.0
round(1.2) +1.0
--------------------
int(1.7) +1.0
floor(1.7) +1.0
round(1.7) +2.0
--------------------
int(-0.2) +0.0
floor(-0.2) -1.0
round(-0.2) +0.0
--------------------
int(-0.7) +0.0
floor(-0.7) -1.0
round(-0.7) -1.0
--------------------
int(-1.2) -1.0
floor(-1.2) -2.0
round(-1.2) -1.0
--------------------
int(-1.7) -1.0
floor(-1.7) -2.0
round(-1.7) -2.0


5.6.3 仅用于整数的函数

除了适应于所有数值类型的内建函数之外,Python 还提供一些仅适用于整数的内建函数(标准整数和长整数)。这些函数分为两类,一类用于进制转换,另一类用于ASCII 转换。

进制转换函数

Python 还提供了两个内建函数来返回字符串表示的8 进制和16 进制整数。它们分别是 oct()和 hex()。它们都接受一个整数(任意进制的)对象,并返回一个对应值的字符串对象。eg:

>>> hex(255)
'0xff'
>>> hex(23094823l)
'0x1606627L'
>>> hex(65535*2)
'0x1fffe'
>>> oct(255)
'0377'
>>> oct(23094823l)
'0130063047L'
>>> oct(65535*2)
'0377776'

ASCII 转换函数

Python 也提供了ASCII码与其序列值之间的转换函数。每个字符对应一个唯一的整数(0-255)。函数chr()接受一个单字节整数值,返回一个字符串,其值为对应的字符。函数ord()则相反,它接受一个字符,返回其对应的整数值。

>>> ord('a')
97
>>> ord('A')
65
>>> ord('0')
48
>>> chr(97)
'a'
>>> chr(65L)
'A'
>>> chr(48)
'0'

表5.7 仅适用于整数的内建函数

5.7 其他数字类型

5.7.1 布尔“数”

  • 尽管布尔值看上去是“True” 和“False,但是事实上是整型的子类,对应与整数的1 和0:

  • 有两个永不改变的值 True 或False。

  • 布尔型是整型的子类,但是不能再被继承而生成它的子类。

  • 没有__nonzero__()方法的对象的默认值是 True。

  • 对于值为零的任何数字或空集(空列表、空元组和空字典等)在Python 中的布尔值都是False。

  • 在数学运算中,Boolean 值的True 和False 分别对应于1 和 0。

  • 以前返回整数的大部分标准库函数和内建布尔型函数现在返回布尔型。

  • True 和False 现在都不是关键字,但是在Python 将来的版本中会是。

所有Python 对象都有一个内建的True 或False 值,下面是使用内建类型布尔值的一些例子:

# intro
>>> bool(0) 
False
>>> bool('0') 
True
>>> bool([]) 
False
>>> bool ( (1,) ) 
True
# 使用布尔数
>>> foo = 42
>>> bar = foo < 100
>>> bar
True
>>> print bar + 100
101
>>> print '%s' % bar
True
>>> print '%d' % bar
1
# 无 __nonzero__()
>>> class C: pass
>>> c = C()
>>> bool(c) 
True
>>> bool(C) 
True
# 重载 __nonzero__() 使它返回 False
>>> class C:
... def __nonzero__(self):
... return False
...
>>> c = C()
>>> bool(c) 
False
>>> bool(C) 
True
# 哦,别这么干!! (无论如何不要这么干!)
>>> True, False = False, True
>>> bool(True) False

5.7.2 十进制浮点数

从Python2.4 起(参阅PEP327)十进制浮点制成为一个Python 特性。这主要是因为下面的语句经常会让一些编写科学计算或金融应用程序的程序员抓狂:

>>> 0.1
0.1000000000000001
为什么会这样?这是因为语言绝大多数C 语言的双精度实现都遵守IEEE 754 规范,其中52 位用于底。因此浮点值只能有52 位精度,类似这样的值的二进制表示只能象上面那样被截断。0.1 的二进制表示是0.11001100110011 . . .
因为最接近的二进制表示就是.0001100110011...或 1/16 +1/32 + 1/256 + . . .
你可以看到,这些片断不停的重复直到舍入出错。如果我们使用十进制来做同样的事情,感觉就会好很多,看上去会有任意的精度。注意下面,你不能混用十进制浮点数和普通的浮点数。你可以通过字符串或其它十进制数创建十进制数浮点数。你必须导入 decimal 模块以便使用 Decimal 类:
>>> from decimal import Decimal
>>> dec = Decimal(.1)
Traceback (most recent call last): File "<stdin>", line 1, in ?
File "/usr/local/lib/python2.4/decimal.py", line 523, in __new__
raise TypeError("Cannot convert float to Decimal. " +
TypeError: Cannot convert float to Decimal. First convert the float to
a string
>>> dec = Decimal('.1')
>>> dec
Decimal("0.1")
>>> print dec
0.1
>>> dec + 1.0
Traceback (most recent call last): File "<stdin>", line 1, in ?
File "/usr/local/lib/python2.4/decimal.py", line 906, in __add__
other = _convert_other(other)
File "/usr/local/lib/python2.4/decimal.py", line 2863, in
_convert_other
raise TypeError, "You can interact Decimal only with int, long or
Decimal data types."
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>
>>> dec + Decimal('1.0') Decimal("1.1")
>>> print dec + Decimal('1.0')
1.1

你可以从 Python 文档中读取相关的 PEP 以了解十进制数。值得庆幸的是,十进制数和其它数值类型一样, 可以使用同样的算术运算符。由于十进制数本质上是一种用于数值计算的特殊类, 我们在本章的剩余部分将不再专门讲解十进制数。

5.8 相关模块

在Python 标准库中有不少专门用于处理数值类型对象的模块,它们增强并扩展了内建函数的功能和数值运算的功能。 表5.8 列出了几个比较核心的模块。

对高级的数字科学计算应用来说,你会对著名的第三方包 Numeric(NumPy) 和SciPy 感兴趣。关于这两个包的详细请访问下面的网址。

http://numeric.scipy.org/

http://scipy.org/

表5.8 数字类型相关模块

核心模块: random

当你的程序需要随机数功能时,random 模块就能派上用场。该模块包含多个伪随机数发生器,它们均以当前的时间戳为随机数种子。这样只要载入这个模块就能随时开始工作。下面列出了该模块中最常用的函数:

两个整数参数,返回二者之间的随机整数

  • randrange() 它接受和 range() 函数一样的参数, 随机返回range([start,]stop[,step])结果的一项

  • uniform() 几乎和 randint()一样,不过它返回的是二者之间的一个浮点数(不包括范围上限)。

  • random() 类似 uniform() 只不过下限恒等于0.0,上限恒等于1.0

  • choice() 随机返回给定序列(关于序列,见第六章)的一个元素

到这儿,我们的 Python 数值类型之旅就该结束了。

表5.9 总结了数值类型的所有内建函数和运算符。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!