Python 数字

作者: 一去、二三里
个人微信号: iwaleon
微信公众号: 高效程序员

在 Python 中,对于数字的定义很简单 - 整数、浮点数和复数,分别被定义为 int、float 和 complex 类。只要数学不是体育老师教的,绝大部分人学起来都不会有任何问题。

对于数字而言,除了进行基本的运算(例如:算术运算、比较运算)之外,Python 还提供了类型间的相互转换功能,以及其他的高级操作。

数字类型

在 Python 中,支持三种不同的数字类型:

  • int(整型):也被称为整数,是正或负整数,不带小数点。
  • float(浮点型):由整数部分与小数部分组成,浮点型也可以使用科学计数法表示。
  • complex(复数):以 x + yj 的形式构成,其中 x 是实部,y 是虚部。

注意: Py3.x 去除了 long 类型,现在只有一种整型 - int,表示为长整型。

>>> type(5)  # 整型
<class 'int'>
>>> 
>>> type(2.5)  # 浮点型
<class 'float'>
>>> 
>>> c = 2.5 + 5.0j  # 复数
>>> type(c)
<class 'complex'>

整数溢出?

天文数字:形容非常大的数字,已经无法用一个确切的数来形容。

对于很多编程语言来说,天文数字是需要被正视的,因为往往会引发整数溢出问题。但是,在 Python 中无需忧虑,因为它支持“无限精度”的整数。

来感受一下:

>>> i = 2 ** 500  # 2 的 500 次幂
>>> i
3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376

哇,多么幸运,Python 做出了如此精妙的安排。。。

虽然整数可以是任意长度,但是浮点数只能精确到 15 位小数(16 位不准确)。

>>> f = 0.12345678901234567890  # 值被截断
>>> f
0.12345678901234568

注意: f 的值被截断。

数字系统

对于绝大部分人来说,每天处理的数字都是十进制(以 10 为基数)数字系统。但是程序员(尤其是搞嵌入式的),往往需要使用二进制(以 2 为基数)、八进制(以 8 为基数)和十六进制(以 16 为基数)数字系统。

在 Python 中,可以在数字前面放置相应的前缀来表示这些数字。

数字系统前缀
十进制(Decimal)
二进制(Binary)‘0b’ 或者 ‘0B’
八进制(Octal)‘0o’ 或者 ‘0O’
十六进制(Hexadecimal)‘0x’ 或者 ‘0X’

来看一些示例:

>>> 5  # 十进制
5
>>> 
>>> 0b1010  # 二进制
10
>>> 
>>> 0o15  # 八进制
13
>>>
>>> 0xFB  # 十六进制
251

十进制还可以转换为二进制、八进制、十六进制:

>>> dec = 20  # 十进制
>>> 
>>> bin(dec)  # 十进制转二进制
'0b10100'
>>> 
>>> oct(dec)  # 十进制转八进制
'0o24'
>>> 
>>> hex(dec)  # 十进制转十六进制
'0x14'

类型转换

一般情况下,数据的类型的转换通常是由编译系统自动进行的,不需要人工干预,所以被称为隐式类型转换。但如果程序要求一定要将某一类型的数据转换为另外一种类型,则可以利用强制类型转换运算符进行转换,这种强制转换过程称为显式类型转换

在进行数字运算(例如:加法、减法)时,如果其中的一个操作数是浮点数,则会将整数隐式(自动)转换为浮点数。

>>> 2 + 3.0
5.0

可以看到,2(整数)被转换为 2.0(浮点数),计算结果(5.0)也是一个浮点数。

除此之外,还可以使用 int()、float() 和 complex() 等内置函数来显式转换类型,这些函数甚至可以将字符串转换为数字。

>>> int(2.3)
2
>>> int(-2.8)
-2
>>> float(5)
5.0
>>> complex('3+5j')
(3+5j)

从 float 转换为 int 时,数字将被截断(整数更接近零)。

Decimal

通常,在使用内置类 float 时,会执行一些“匪夷所思”的计算。

我们知道 1/3 等于 0.333…(无限循环),0.1 + 0.2 等于 0.3,但 Python 似乎不这么认为。

>>> 1/3
0.3333333333333333
>>> 
>>> 0.1 + 0.2
0.30000000000000004

What?难道是眼花了?和数学知识不一样?(一脸懵逼。。。)

事实证明,浮点数在计算机硬件中以二进制小数来表示,因为计算机只能理解二进制(0 和 1)。出于这个原因,大部分十进制小数都不能准确地存储在计算机中。

例如,十进制小数 0.1,将转换为无限长的二进制小数 0.000110011001100110011…,而计算机存储的位数是有限的。也就是说,转换为二进制后,只会接近十进制的 0.1,但永远不会相等。

因此,这是计算机硬件的局限性,而不是 Python 中的错误。

为了克服这个问题,可以使用 Python 自带的 decimal 模块。虽然浮点数的精度最高可达 15 位,但 decimal 模块可自定义精度。

>>> import decimal
>>> 
>>> 0.1
0.1
>>> 
>>> decimal.Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> 
>>> decimal.getcontext()  # 当前上下文
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> 
>>> decimal.getcontext().prec  # 精度默认 28 位
28
>>> 
>>> d = decimal.Decimal(1) / decimal.Decimal(9)
>>> d
Decimal('0.1111111111111111111111111111')
>>> 
>>> decimal.getcontext().prec = 3  # 将精度修改为 3 位
>>> 
>>> d = decimal.Decimal(1) / decimal.Decimal(9)
>>> d
Decimal('0.111')

除此之外,它也保留了重要意义。我们知道 25.50 比 25.5 更精确,因为 25.50 有两个有效的小数位。

>>> from decimal import Decimal as D
>>>
>>> D('0.1') + D('0.2')
Decimal('0.3')
>>> 
>>> D('1.2') * D('2.50')
Decimal('3.000')

注意: 计算结果末尾的 0

有人可能会问:既然 Decimal 这么棒,为什么每次不使用 Decimal 来代替 float 呢?主要原因是效率,float 运算要比 Decimal 运算更快。

何时使用 Decimal,而不是 float 呢?在以下情况下,通常使用 Decimal。

  • 当在做金融应用时,需要精确表示。
  • 当想要控制所需的精度级别时
  • 当想要实现有效的小数位概念时
  • 当我们想要像在学校里学到的那样进行小数运算时

fractions(有理数)

fractions 模块提供了涉及分数的操作,该模块支持有理数运算。

一个 Fraction 实例可以由一对整数、另一个有理数、或者一个字符串来构造。

>>> import fractions
>>> 
>>> fractions.Fraction(1.5)
Fraction(3, 2)
>>> 
>>> fractions.Fraction(10)
Fraction(10, 1)
>>> 
>>> fractions.Fraction(3, 5)
Fraction(3, 5)
>>> 
>>> print(fractions.Fraction(1.5))
3/2

当从 float 创建 Fraction 时,可能会得到一些不寻常的结果,这是由于之前讨论的不完美的二进制浮点数造成的。

幸运的是,fraction 也允许用字符串进行实例化,这是使用十进制数时的首选方案。

>>> from fractions import Fraction
>>> 
>>> print(Fraction(1.1))  # 浮点数 1.1
2476979795053773/2251799813685248
>>> 
>>> print(Fraction('1.1'))  # 字符串 '1.1'
11/10

此外,该数据类型也支持所有基本操作。

>>> from fractions import Fraction as F
>>> 
>>> F(1,3) + F(1,3)
Fraction(2, 3)
>>> 
>>> 1 / F(2,3)
Fraction(3, 2)
>>> 
>>> F(-2,5) < 0
True

math(数学函数)

math 模块用于处理数学相关的运算,例如:三角学、对数等。

>>> import math
>>> 
>>> math.pi  # 圆周率 π
3.141592653589793
>>>
>>> math.e  # 自然常数
2.718281828459045
>>> 
>>> math.cos(math.pi)  # 余弦
-1.0
>>> 
>>> math.log10(100)  # 以 10 为基数的 100 的对数
2.0
>>>
>>> math.pow(2, 5)  # 2**5(2 的 5 次方) 运算后的值
32.0
>>>
>>> math.sqrt(9)  # 9 的平方根
3.0
>>>
>>> math.factorial(5)  # 5!(5 的阶乘)
120

random(生成伪随机数)

random 模块用于生成伪随机数。随机数可用于数学、游戏、安全等领域,还经常被嵌入到算法中,用以提高算法效率,并提高程序的安全性。

>>> import random
>>> 
>>> l = ['p', 'y', 't', 'h', 'o', 'n']
>>> 
>>> random.choice(l)  # 从序列 l 中随机挑选一个元素
'y'
>>> 
>>> random.shuffle(l)  # 将序列 l 的所有元素随机排序
>>> l
['t', 'y', 'h', 'p', 'n', 'o']
>>> 
>>> random.randrange(0, 10)  # 从指定范围内,按指定基数(缺省值为 1)递增的集合中获取一个随机数
3
>>> 
>>> random.random()  # 随机生成一个实数,范围 [0,1)。
0.09207929369477685

上述是数字相关的各模块的一些常见应用,完整的功能列表不再赘述,请参考 Python 文档。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一去丶二三里

有收获,再打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值