2.Python数值类型

2.1 数值类型基础知识

在Python 中,数字并不真的只是一种对象类型,而是一组相似类型的分类。

Python 数值类型工具包括:
• 整数和浮点对象
• 复数对象
• 小数:固定精度对象
• 分数:有理数对象
• 集合:带有数值运算的集合体
• 布尔值:真和假
• 内置函数和模块: round 、math 、random 等
• 表达式: 无限制整数精度;位运算;十六进制、八进制和二进制格式
• 第三方扩展:向量、库、可视化、作图等

2.1.1 数值字面量

Python数值字面量和构造函数:

常量 解释
1234, -24, 0, 99999999 整数(无穷大小)
1.23, 1., 3.14e-10, 4E210, 4.0e+210 浮点数
0o177, 0x9ff, 0b101010 八进制、十六进制和二进制常量
3+4j, 3.0+4.0j, 3j 复数常量
set('spam'), 集合
Decimal('1.0'), Fraction(1, 3) 小数和分数扩展类型
bool(X), True, False 布尔类型和常数

浮点型字面量

浮点数带一个小数点,python浮点数可以带上科学计数法标志e或者E。如果数字带有小数点,哪怕小数点后面没有数字(如1.),python也是创建浮点数对象。浮点数在Python中采用“双精度”。

八进制/十六进制/二进制字面量

十六进制字面量以0x或0X开头,后面接着十六进制的数字0-9和A-F;
八进制字面量以0o或oO开头,后面接着八进制数字0-7;
二进制字面量以0b或0B开头,后面接着二进制数字0-1;

复数字面量

复数字面量是以实部+虚部组成,其中虚部以j或J结尾,实部可以忽略,复数可以通过 complex(real, imag) 来创建。

2.1.2 Python表达式运算符

操作符 描述
yield x 生成器函数发送协议
lambda args: expression 生成匿名函数
x if y else z 三元选择表达式(当y为真时,才会计算x)
x or y 逻辑或(只有 x 为假,才会计算 y)
x and y 逻辑与(只有 x 为真,才会计算 y)
not x 逻辑非
x in y, x not in y 成员关系(可迭代对象、集合)
x is y, x is not y 对象实体测试
x < y, x <= y, x > y, x >= y 大小比较,集合子集和超集
x == y, x != y 值相等性操作符
x | y 位或,集合并集
x ^ y 位异或,集合对称差
x & y 位与,集合交集
x << y, x >> y 左移或右移 y 位
x + y 加法,合并
x - y 减法,集合差集
x * y 乘法,重复
x % y 余数,格式化
x / y, x // y 除法:真除法(x / y)或 floor 除法(x // y,即向下取整)
-x, +x 一元减法,识别
~x 按位求补(取反)
x ** y 幂运算
x[i] 索引(序列、映射及其他)
x[i:j:k] 分片
x(...) 调用(函数、方法、类及其他可调用的)
x.attr 属性引用
(...) 元组,表达式,生成器表达式
[...] 列表,列表解析
字典、集合、集合和字典解析

上表中自上而下运算优先级递增。

混合运算遵循运算级优先级

在Python中混合运算将遵循运算符优先级,圆括号可以将表达式进行分组,表达式将优先执行圆括号中的运算,推荐将复杂的表达式使用圆括号增加可读性。

混合类型向上转换

在混合类型的表达式中, Python 首先将被操作数值类型的对象转换成其中最复杂的操作数的类型,然后再对相同类型的操作数进行数学运算。 Python 是这样划分数值类型的复杂度的:整数比浮点数简单,浮点数比复数简单。因此,将一个整数与一个浮点数进行混合运算时,整数将会被向上转换成浮点数,之后再与浮点数进行运算。

混合类型转换仅适用于数值类型的混合,而不能用于其他类型之间转换。如一个字符串和一个整数相加会产生错误。同时非数值混合类型之间也不允许比较。

2.1.3 数字的实际运用

变量与基础表达式

在Python 中:
• 变量在第一次赋值时被创建。
• 变量在表达式中使用时,会被替换成它们的值。
• 变量在表达式中使用之前,必须已被赋值。
• 变量引用对象,而且从不需要事先声明。
使用一个未被赋值的变量将会出现“未定义”错误。

>>> a = 3
>>> b = 4  # 赋值将自动创建变量a和变量b
>>> c  # 使用未赋值的变量将出现未定义错误
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    c
NameError: name 'c' is not defined

普通比较与链式比较

普通比较:

>>> 1 < 2
True
>>> 2.0 >= 1.0
True
>>> 2.0 == 2.0
True
>>> 2.0 != 2.0
False

python还允许把多个比较链接起来执行范围测试:

>>> X = 2
>>> Y = 4
>>> Z = 6
>>> X < Y < Z  # 相当于 X < Y and Y < Z
True
>>> X < Y > Z  # 相当于 X < Y and Y > Z
False
>>> 1 == 2 < 3 # 相当于 1== 2 and 2 < 3,而并不是把 1==2的结果False与3进行小于比较
False

除法:经典除法、向下取整除法和真除法

在Python 3 . X 中,现在总是执行真除法,不管操作数的类型,都返回包含任何小数部分的一个浮点数结果。//执行向下取整除法,它截除掉余数并针对整数操作数返回一个整数,如果有任何一个操作数是浮点数类型,则返回一个浮点数。

>>> 5 / 2 , 5 / -2
(2.5, -2.5)
>>> 5 // 2 , 5 // -2  # // 是向下取整,即小于商的最大整数
(2, -3)
>>> 5 / 2.0 , 5 / -2.0
(2.5, -2.5)
>>> 5 // 2.0, 5 // -2.0
(2.0, -3.0)

复数

>>> 1j * 1J
(-1+0j)
>>> 2 + 1j * 3
(2+3j)
>>> (2 + 1j) * 3
(6+3j)

十六进制、八进制和二进制:字面量和转换

字面量:

>>> 0o1, 0o20, 0o377
(1, 16, 255)
>>> 0x01, 0x10, 0xFF
(1, 16, 255)
>>> 0b1, 0b10000, 0b11111111
(1, 16, 255)

python提供了内置函数将十进制数字转换为十六进制、八进制和二进制数字:

  • oct 函数会将十进制数转换为八进制数字的字符串;
  • hex 函数会将十进制转换为十六进制数字的字符串;
  • bin 函数会将十进制数转换为二进制数字的字符串;
>>> oct(64), hex(64), bin(64)
('0o100', '0x40', '0b1000000')

内置函数int 会将一个数字的字符串转换为一个整数,并能通过可选的第二位参数来确定转换后数字的进制。

>>> 64, 0o100, 0x40, 0b1000000
(64, 64, 64, 64)
>>> int('64'), int('100', 8), int('40', 16), int('1000000', 2)
(64, 64, 64, 64)
>>> int('0o100', 8), int('0x40', 16), int('0b1000000', 2)

eval函数可以将字符串当作python代码来执行,因此也可以把进制数字字符串转换为整数:

>>> eval('64'), eval('0O100'), eval('0x40'), eval('0b1000000')
(64, 64, 64, 64)

也可以使用字符串格式化将整数转换为指定进制的字符串:

>>> '{0:o}, {1:x}, {2:b}'.format(64, 64, 64)
'100, 40, 1000000'

按位运算

>>> x = 1  # x = 0b0001
>>> x << 2  # 0b0001 << 2 = 0b0100
4
>>> x >> 2  # 0b0001 >> 2 = 0b0000 
0
>>> x | 2  # 0b0001 | 0b0010 = 0b0011
3
>>> x & 1  # 0b0001 & 0b0001 = 0b0001
1
>>> x ^ 3  # 0b0001 ^ 0b0011 = 0b0010
2

Python 3.1 和2.7 引入了一个新的整数方法bit_length, 它允许我们查询以二进制表示一个数字的值时所需的位数:

>>> bin(X), X.bit_length(), len(bin(X)) - 2
('0b1100011', 7, 7)

内置数值工具

  • 内置数学函数:
    • pow:计算幂
    • abs:计算绝对值
    • sum:求和
    • round:向上取整(四舍五入)
    • max:求最大值
    • min:求最小值
>>> pow(2, 4), 2 ** 4, 2.0 ** 4.0
(16, 16, 16.0)

>>> abs(-42.0), sum((1, 2, 3, 4))
(42.0, 10)

>>> min((1, 2, 3, 4)), max((1, 2, 3, 4))
(1, 4)

>>> round(2.56), round(2.46), round(2.567, 2)  # round还可以指定小数的舍入位数
(3, 2, 2.57)
>>> '%.1f' % 2.567, '{0:.2f}'.format(2.567)  # 字符串格式化也可使小数按位舍入
('2.6', '2.57')

内置函数位于一个隐藏的命名空间内,python会自动在这个命名空间中搜索名字,这个命名空间对应builtins的标准库模块。

  • 内置模块math:
>>> import math
>>> math.pi, math.e
(3.141592653589793, 2.718281828459045)

>>> math.sin(math.pi / 3), math.cos(math.pi / 3), math.tan(math.pi / 3)
(0.8660254037844386, 0.5000000000000001, 1.7320508075688767)

>>> math.sqrt(2)
1.4142135623730951
  • 内置模块random

random提供了一系列的随机处理函数工具:

random.random函数:返回一个随机的0到1之间的浮点数

random.randint函数:返回一个两个数字之间的随机整数

random.choice函数:从一个序列中随机挑选一项

random.shuffle函数:随机打乱列表中的元素

>>> import random
>>> random.random()
0.6190454094520157
>>> random.random()
0.88053113013268

>>> random.randint(1, 10)
9
>>> random.randint(1, 10)
1

>>> random.choice(['a', 'b', 'c'])
'c'
>>> random.choice(['a', 'b', 'c'])
'b'

>>> abc = [ 'a', 'b', 'c']
>>> random.shuffle(abc)
>>> abc
['b', 'c', 'a']
>>> random.shuffle(abc)
>>> abc
['a', 'b', 'c']

2.2 小数类型

python中还有一种小数对象(Decimal),小数对象位于decimal模块中,创建时需要调用decimal模块的Decimal构造函数来创建小数,而不是通过字面量表达式来创建。

小数很像浮点数,但是小数有固定的位数和小数点,即小数是精度固定的浮点数

小数基础知识

浮点数的运算缺乏精确性:

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17

使用小数对象将使结果更加准确:

>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

在表达式中使用不同精度的小数时,python会自动转换为最高的小数精度:

>>> Decimal('0.1') + Decimal('0.10') + Decimal('0.10') - Decimal('0.3')
Decimal('0.00')

也可以使用浮点数来创建小数对象,这一转换是精确的,但是有时候结果会产生庞大的小数位数:

Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)
Decimal('2.775557561565156540423631668E-17')

设置全局小数精度

decimal模块还可设置全局的小数数值精度和舍入模式等:

>>> import decimal
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')  # 小数的默认有效精度是28

# 设置小数精度
>>> decimal.getcontext().prec = 4  
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429')

# 设置舍入模式,decimal.ROUND_HALF_UP表示向上舍入,decimal.ROUND_HALF_DOWN表示向下舍入
>>> decimal.getcontext().rounding = decimal.ROUND_HALF_UP
>>> Decimal('3') / Decimal('2.2')
Decimal('1.364')

小数上下文管理器

可以使用with上下文管理语句创建小数的上下文管理器,这样在with语句中设置的精度将会在退出with语句后重置:

# 创建上下文管理器
>>> with decimal.localcontext() as ctx:
        ctx.prec = 2
        decimal.Decimal(1) / decimal.Decimal(7)

    
Decimal('0.14')
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429')

2.3 分数类型

python中还有分数类型(Fraction),它实现了一个有理数对象,它显式地保留了一个分子和分母,从而避免了浮点数运算的不精确性。

分数基础知识

与小数类型类似,分数类型位于fractions模块中,需要导入fractions模块的构造函数Fraction并传递一个分子和分母来产生一个分数:

>>> from fractions import Fraction
>>> Fraction(1, 3)
Fraction(1, 3)
>>> Fraction(4, 6)
Fraction(2, 3)
>>> x = Fraction(1, 3)
>>> y = Fraction(4, 6)  # 分数会自动约分
>>> x
Fraction(1, 3)
>>> y
Fraction(2, 3)
>>> print(y)
2/3

分数对象也可以通过浮点数字符串来创建:

>>> Fraction('.25')
Fraction(1, 4)

>>> Fraction('1.25')
Fraction(5, 4)

一旦创建了分数对象,就可以用于平常的数学表达式中:

>>> x + y
Fraction(1, 1)
>>> x - y
Fraction(-1, 3)
>>> x * y
Fraction(2, 9)

分数转换和混用类型

  • 浮点数转分数:浮点数对象有一个as_integer_ratio()方法,可以产生分子分母比;另外,分数有一个from_float方法,可以接受一个浮点数返回对应的分数
>>> f = 0.25
>>> z = Fraction(*f.as_integer_ratio())  # *号是一种特殊的语法,它可以把一个元组展开成单独的参数
>>> z
Fraction(1, 4)
>>> Fraction.from_float(0.75)
Fraction(3, 4)
  • 分数转浮点数:float函数可以直接将Fraction对象转换成浮点数
>>> z
Fraction(1, 4)
>>> float(z)
0.25

表达式中允许分数和浮点数混合使用:

>>> x
Fraction(1, 3)
>>> x + 2               # Fraction + int -> Fraction
Fraction(7, 3)
>>> x + 2.0             # Fraction + float -> float
2.3333333333333335
>>> x + (1./3)
0.6666666666666666
>>> x + (4./3)
1.6666666666666665
>>> x + Fraction(4, 3)  # Fraction + Fraction -> Fraction
Fraction(5, 3)

尽管可以把浮点数转换成分数,但是某种情况下,这么做会有不可避免的精度损失,因为这个数字在其最初的浮点数形式下就是不精确的,必要时,可以通过限制分母的最大值来简化这样的结果。

>>> (4 / 3).as_integer_ratio()
(6004799503160661, 4503599627370496)

>>> x
Fraction(1, 3)
>>> a = x + Fraction(*(4 / 3).as_integer_ratio())
>>> a
Fraction(22517998136852479, 13510798882111488)
>>> 22517998136852479 / 13510798882111488
1.6666666666666665
>>> a.limit_denominator(10)
Fraction(5, 3)
posted @ 2024-03-04 12:00  N1rv2na  阅读(55)  评论(0)    收藏  举报