一、数值数据类型讲解

1.数值类型

Python 数值类型用于存储数字,支持多种数字类型,如整型、浮点型、复数等:

【1】整型(int),也就是整数,即不带小数部分的数字。

注意:Python3 中的整型数据没有大小限制,支持无穷精度,不再像Python2中还要区分为int和long类型。另外,布尔(bool)类型是整型的子类型,后面会讲。

整数除了十进制整数外,还可以写成二进制、八进制、十六进制甚至是其它进制的整数,常见的有:

  • 当一个整数以0b0B开头,其后都是0、1时,默认识别为二进制整数,如0b10001(对应十进制17)。

  • 当一个整数以0o0O开头(数值零和大、小写的字母o),其后都是0-7之间的数值时,默认识别为8进制整数,如0o123(对应十进制83)。

  • 当一个整数以0x0X开始,其后都是[0-9][a-f][A-F]之间的字符时,默认识别为十六进制。如0xF5(对应十进制245)

【2】浮点型(float),也就是浮点数,即有小数部分的数字,由整数部分和小数部分组成。任何时候浮点数都是不精确的,这与计算机存储方式原理有关

  • 科学计数法表示的值也为浮点型,例如2.5e2 (虽然它的结果是250=2.5 x 10的2次方,看起来像整形 ,但2.5e2是浮点类型)。

  • 当浮点数参与运算时,会以浮点数的规则进行运算,结果为浮点数;除法运算时,即便都是整数,结果也会是浮点数类型。

  • python中的浮点数精度和C语言的双精度浮点数精度相同。

【3】其他数值类型:复数、分数、小数、有理数、无理数等,用得比较少。

python中的数值类型是不可变对象,不可变意味着不可在原处修改。比如说定义一个变量a的值为666,a = 666,那么内存中就会有一个内存块保存数值对象666,如果修改它,比如对它加上1:a = a + 1,那么python将创建一个新的内存块用来保存新的数值对象667,而不是在666那个内存块中直接修改为667,python中的垃圾回收机制会把那个原始的数值666回收丢弃。

2.数值运算

python中的数值支持各种计算:加减乘除(+ - * /) 、取正负 (+x -x)、做比较(> <)、取模/取余 (%)、地板除法(//)、幂运算(**)

#我们在解释器里进行运算,解释器会立刻告诉我们结果(如下);如果在IDE里,还要进行print才可以看到结果。

#加减乘除四则运算
>>> 4 + 5
9
>>> 6 - 2
4
>>> 5 * 4
20
>>> 8 / 2
4.0

#作比较,返回True或False
>>> 4 > 5
False
>>> 6 >= 6
True


# /:实现的是真除法。在python中,它总是返回浮点数值。
>>> 17 / 3  
5.666666666666667

# //:实现的是floor地板除法,它会去掉除法运算后的小数位,以便得到小于运算结果的最大整数。如果参与运算的有浮点数,则返回浮点数,否则返回整数
>>> 17 // 3
5
>>> 7//2.0
3.0

# %操作符返回除法的余数,也就是取模运算,也叫mod运算
>>> 17 % 3  
2

#在math模块中,有地板函数math.floor()和天花板函数math.ceil()。它们的意义可以根据现实中地板、空气、天花板的高低位置来考虑。地板位于空气之下,地板运算的返回值是比空气小的最大整数,天花板位于空气之上,天花板运算的的返回值是比空气大的最小整数
math.floor(11.46)=math.floor(11.68)=math.floor(11.5)=11
math.floor(-11.46)=math.floor(-11.68)=math.floor(-11.5)=-12

math.ceil(11.46)=math.ceil(11.68)=math.ceil(11.5)=12
math.ceil(-11.46)=math.ceil(-11.68)=math.ceil(-11.5)=-11

# **是次幂运算,5的2次方是25
>>> 5 ** 2  
25

**注意1:**有浮点数参与的运算,结果为浮点数,即便其中可能有整数也参与了运算:

>>> 3 * 3.75 / 1.5
7.5
>>> 7.0 / 2
3.5

**注意2:**关于浮点数的运算

#例如,按照数学运算时,1.1-0.9=0.2,但实际得到的结果为:
>>> 1.1-0.9
0.20000000000000007
#它以高精度的极限趋近的值来显示。上面的趋近结果大于按照数学运算结果,但并不总是如此,例如下面的运算则是小于数学运算的结果:
>>> 3.3-3.2
0.09999999999999964

解释:由于硬件的原因,使得计算机对于浮点数的处理总是不精确的。所以尽量不要对两个浮点数数进行等值==和不等值!=比较.如果非要比较,应该通过它们的减法求绝对值,再与一个足够小(不会影响结果)的值做不等比较,例如:

>>> (3.2-2.8) == 0.4
False

>>> abs((3.2-2.8)-0.4) < 0.0002
True

另外,浮点数并非总是输出很长精度的值。例如:

>>> 3.2+3.2
6.4
>>> 3/10
0.3

浮点数有两个特殊方法,一个是is_integer(),用来测试这个浮点数是否是整数,另一个是as_integer_ratio(),可以将浮点数转换成分子分母组成的元组,不过这个方法并非总是如你所想的那样友好,返回的值可能很长。例如:

>>> (3.0).is_integer()
True
>>> (3.2).is_integer()
False

>>> (2.5).as_integer_ratio()
(5, 2)
>>> (2.6).as_integer_ratio()
(5854679515581645, 2251799813685248)

浮点数总是不精确的,而且不能指定小数位数。但在python中,有一个专门的小数模块decimal,它可以提供精确的小数运算,还有一个分数模块fractions,也能提供精确的小数运算。后面会讲到,按需参考。

**注意3:**加号和乘号在数值运算里,就是加和乘,但在字符串里,它们还有别的用处,后续会讲到。

+可以连接字符串,例如"abc" + "def"得到'abcdef'
*可以重复字符串次数,例如"a"*3得到"aaa","ab"*3得到"ababab"

**注意4:**除了上面的基础算术运算符,Python还支持其他的运算符,例如:取反(~)、位移(>>)、位与(&)、位异或(^)、逻辑与(and)、逻辑或(or),不过一般很少用:

3.数值类型转换

经常遇到把数据从float类型转换成int类型的需求,也存在将int类型转成float类型的情况,我们通过int()和float()来实现。

>>> float(33)
33.0
>>> int(22.34)
22

#以下四个内置函数,常用的只有int() 与 float()。
int(x) 将x转换为一个整数。
float(x) 将x转换到一个浮点数。
complex(x) 将x转换到一个复数,实数部分为 x,虚数部分为 0。
complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y,x 和 y 是数字表达式。

4.数值进制转换

4.1 其他进制转成十进制

#二进制1101010转成十进制为106
value = int('1101010', 2)
print(value)        # 106

#八进制125转成十进制为85
value = int('125', 8)
print(value)        # 85

#十六进制3f2a1转成十进制为258721
value = int('3f2a1', 16)
print(value)        # 258721

使用int函数可以将二进制,八进制,十六进制的数值转成十进制数值,而且字符串的开头可以不携带进制的标识,如果你喜欢使用,也可以写成 int(‘0x3f2a1’, 16)。注意int()函数的第一个参数应该为字符串类型(也就是要加上引号)。

4.2 十进制转成其他进制

十进制转二进制使用bin()函数, 十进制转八进制使用oct()函数, 十进制转十六进制使用hex()函数,转换后得到的值会带进制标识。

print(bin(106))     # 0b1101010 十进制转二进制
print(oct(85))      # 0o125     十进制转八进制
print(hex(258721))  # 0x3f2a1   十进制转十六进制

4.2 其他进制转二进制

上面已经提到十进制转二进制用bin()函数即可,但并没有函数可以实现直接将八进制或十六进制数转成二进制,因此需要借用int()函数先将八/十六进制的数转成十进制,然后使用bin()函数将十进制数转成二进制

print(bin(666))   # 十进制转二进制
print(bin(int('0O125', 8)))   # 八进制转二进制
print(bin(int('0x3f2a1', 16)))  # 十六进制转二进制

4.4 二进制转其他进制

二进制转其他进制需要用十进制做中转,上面已经提到二进制转十进制用int(x,2)函数即可,十进制再转八进制可以使用oct函数;二进制转十六进制也是同理。

print(int('10011',2))			# 二进制转十进制
print(oct(int('0b1101010',2))     # 二进制转八进制
print(hex(int('1101010', 2)))   # 二进制转十六进制

#实际上二进制可以直接用oct()直接转为八进制(二进制前面必须加上0b),不经过十进制中转也可以。十六进制则必须经过十进制中转
print(oct(0b1101010))  

4.5 八进制与十六进制互转

十六进制转八进制,可以直接使用oct函数,而八进制转十六进制则需要借助int函数

print(oct(0x3f2a1))     # 十六进制转八进制
print(hex(int('125', 8)))   # 八进制转十六进制

4.6 进制转换方法总结

1.int函数可以将其他三个进制转成10进制,oct函数可以将其他三个进制转成8进制

2.hex只能把10进制转成16进制,其他进制需要先变成10进制后再用hex转16进制

4.bin只能把10进制转成2进制,其他进制需要先变成10进制后再用bin转2进制

4.7 关于int函数补充解释

int()函数能进行进制转换,它的用法格式为:

int(x, base=10)

base指定要将x解释成哪个进制位的数,然后转换成十进制数,也就是前面说的构造一个整数对象。不指定base时,默认解释成10进制。

base的值可以是0或2-36之间的任意一个数,base=0也表示解释成10进制。

例如,将二进制的数转换为十进制整数。

>>> int('0b11',base=2)
3
>>> int('11',base=2)
3
#可以省略"base=",直接写进制

既然x要解释成某个进制的数,那么超出这个进制的数自然不能出现。例如:

  • 将x解释成二进制数的时候,int(x,2)的x里就不能包含除0、1之外的数(当然,前缀0b除外);
  • 解释成7进制,就不能出现0-6以外的数;
  • 解释成8进制,就不能出现0-7以外的数;
  • 解释成11进制,就只能出现0-9、aA这些字符;
  • 12进制就只能出现0-9、aAbB这些字符;
  • 36进制就只能出现0-9、a-z、A-Z这些字符。

例如,将一个字符串解释为15进制,并转换成整数。15进制只能出现0-9、a-eA-E这几个字符。

>>> int('93E', base=15)
2084

5.数学函数

大多需要导入math模块

import math
函数 返回值 ( 描述 )
abs(x) 返回数字的绝对值,如abs(-10) 返回 10。参数可以是整数,浮点数,复数,当参数是复数(complex number)时, 返回这个复数的模。
fabs(x) 返回数字的绝对值,如math.fabs(-10) 返回10.0。和abs()的区别在于,fabs不是内置函数,是在math模块中定义的函数,fabs对复数无效,abs()的参数可以为复数,结果为复数的模。
ceil(x) 返回数字的上入整数,如math.ceil(4.1) 返回 5
floor(x) 返回数字的下舍整数,如math.floor(4.9)返回 4
max(x,y,z…) 返回给定参数的最大值,参数可以为序列。
min(x1, y,z…) 返回给定参数的最小值,参数可以为序列。
log(x) 返回x(>0)的自然对数,如math.log(math.e)返回1.0,math.log(100,10)返回2.0。数字的自然对数是其以数学常数e为底的对数,其中e大约等于2.718281828459,x的自然对数通常写为lnx
log10(x) 返回以10为基数的x(>0)的对数,如math.log10(100)返回 2.0
exp(x) 返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045
modf(x) 返回x的整数部分与小数部分组成的元组,整数部分以浮点型表示。
pow(x, y) x**y =x的y次方,如math.pow(3,2)将返回9.0,pow(3,2)将返回9,如果有第三个参数z,则是先求x的y次方后,再取模(取模运算是求两个数相除的余数),即pow(x,y)%z,注意:pow() 可以通过内置的方法直接调用(不用导入math模块),内置方法会把参数作为整型,也可以通过math模块调用,而 math 模块则会把参数转换为 float,返回浮点数
round(x ,n) 返回浮点数 x 的四舍五入值,如给出 n 值,则代表舍入到小数点后的位数。其实准确的说是保留值将保留到离上一位更近的一端。
sqrt(x) 返回数字x的平方根。返回值永远是float浮点型,经常用来求素数(也叫质数、质因子)

注意1:round(x[,n]):

返回浮点数 x 的四舍五入值,准确的说保留值将保留到离上一位更近的一端(四舍六入),n表示保留n位小数,如果不写的话,默认保留整数,不要小数。

精度要求高的,不建议使用该函数。例如round(2.675, 2) 的返回结果不是2.68,而是2.67,这跟浮点数的精度有关。我们知道在机器中浮点数不一定能精确表达,因为换算成一串 1 和 0 后可能是无限位数的,机器已经做出了截断处理。那么在机器中保存的2.675这个数字就比实际数字要小那么一点点。这一点点就导致了它离 2.67 要更近一点点,所以保留两位小数时就近似到了 2.67。

在Python2.7中,如果距离两端一样远,则保留到离0远的一边。所以round(0.5)会近似到1,而round(-0.5)会近似到-1。

在Python3.5中,如果距离两边一样远,会保留到偶数的一边。比如round(0.5)和round(-0.5)都会保留到0,而round(1.5)会保留到2。

print(round(10.4)) #10
print(round(10.5)) #10
print(round(10.6)) #11
print()
print(round(11.4)) #11
print(round(11.5)) #12
print(round(11.6)) #12
在Python3.5以后的版本,可以得出以下结论:
当个位为奇数,小数部分>=0.5入,其余为舍
当个位为偶数,小数部分>0.5入,其余为舍。
换句话说,当小数为0.5时,奇进偶不进(指个位数的奇偶)

国家标准也已经规定使用 “4舍6入5看齐,奇进偶不进” 取代"四舍五入"。从统计学的角度上来讲,如果大量数据采用四舍五入会造成统计结果偏大。而"奇进偶舍"可以将舍入误差降到最低,它使舍入后的结果误差的均值趋于零,而不是像四舍五入那样逢五就入,导致结果偏向大数,使得误差产生积累,进而产生系统误差。

除非对精确度没什么要求,否则尽量避开用round()函数。近似计算我们还有其他的选择(对浮点数精度要求如果很高的话,请用decimal模块):

  • 使用math模块中的一些函数,比如math.ceiling(天花板除法)。
  • python自带整除,python2中是/,3中是//,还有div函数。
  • 字符串格式化可以做截断使用,例如 “%.2f” % value(保留两位小数并变成字符串)

6.随机数函数

大多需要导入random模块

import random
函数 描述
random() 随机生成一个[0,1)范围内的实数。
uniform(x, y) 随机生成一个[x,y]范围内实数。
choice(seq) 从序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数。
[randrange (start,] stop [,step]) 从指定范围内,按指定基数递增的集合中获取一个随机数,基数默认值为 1。
import random
print(random.randrange(0,100, 4))
#以上代码从0-99中随机选取一个能被4整除的整数(取不到100)
seed(x) 改变随机数生成器的种子seed。如果你不了解其原理,你不必特别去设定seed,Python会帮你选择seed。seed()改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数。我们调用 random.random() 生成随机数时,每一次生成的数都是随机的。但是,当我们每次生成随机数之前都预先使用 random.seed(x) 设定好种子之后,其中的 x 可以是任意数字,如10,这个时候,先调用它的情况下,使用 random() 生成的随机数将会是同一个。
shuffle(lst) 将序列的所有元素随机排序
#random.shuffle 具有破坏性,即便指定相同的随机种子,对同一个列表多次随机的结果也不会相同,所以我们不能动原始的列表。
import random

list = [20, 16, 10, 5]
random.seed(10)
random.shuffle(list)
print("随机排序列表1: ", list)

random.seed(10)
random.shuffle(list)
print("随机排序列表2: ", list)

输出结果:
随机排序列表1 : [5, 10, 16, 20]
随机排序列表2 :  [20, 16, 10, 5]

#下列代码才可以得到相同的随机排序列表。
import random

list = [20, 16, 10, 5]
random.seed(10)
my_list = list[:]
random.shuffle(my_list)
print("随机排序列表1: ", my_list)

random.seed(10)
my_list = list[:]
random.shuffle(my_list)
print("随机排序列表2: ", my_list)

输出结果:
随机排序列表1:  [5, 10, 16, 20]
随机排序列表2:  [5, 10, 16, 20]
#求101-200之间的质数,入门经典题目等看完基础教程再来看即可。
import math
print("101-200之间的素数是:",end="")
for i in range(100,201):#range的范围是左闭右开,要求101-200,就要写(101,200+1)
  for j in range(2,int(math.sqrt(i))+1):
    if(i%j==0):break
  else:
    print("",i,end="")
#结果为:
#101-200之间的素数是: 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199

7.三角函数

函数 描述
acos(x) 返回x的反余弦弧度值。
asin(x) 返回x的反正弦弧度值。
atan(x) 返回x的反正切弧度值。
atan2(y, x) 返回给定的 X 及 Y 坐标值的反正切值。
cos(x) 返回x的弧度的余弦值。
hypot(x, y) 返回欧几里德范数 sqrt(xx + yy)。
sin(x) 返回的x弧度的正弦值。
tan(x) 返回x弧度的正切值。
degrees(x) 将弧度转换为角度,如degrees(math.pi/2) , 返回90.0
radians(x) 将角度转换为弧度

8.数学常量

常量 描述
pi 数学常量 pi(圆周率,也就是π),pi约等于3.1415926535898。
e 数学常量 e,e即自然常数,e约等于2.718281828459。

9.小数类型(Decimal)

如果工作中对小数精确度要求不是很高,可以不看这里。小数模块decimal,它有一个函数Decimal(),它是精确的,可以指定小数位数。

例如,使用浮点数进行如下计算,它本该等于0,但结果却是无限接近于0,原因是计算机硬件用于存储数值位数的空间有限,导致精度有问题。

>>> 0.1 * 3 - 0.3
5.551115123125783e-17

使用decimal模块的Decimal()可以构造精确的小数。例如:

>>> import decimal
>>> decimal.Decimal('0.1') * 3 - decimal.Decimal('0.3')
Decimal('0.0')

注意,Decimal()的参数都是字符串,如果不加引号,它还是会解释成浮点数。

>>> decimal.Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')

Decimal()的运算的结果会取最长的小数位数。

>>> decimal.Decimal('0.1') * 3 - decimal.Decimal('0.300')
Decimal('0.000')

可以设置decimal的精度,也就是小数位数。有两种范围的精度:全局范围、局部范围。

例如,没有设置精度时,会保留很多位数的小数。

>>> import decimal
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')

设置全局范围的精度为4,即保留4位小数:

>>> import decimal
>>> decimal.getcontext().prec = 4
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429')

全局范围的精度表示整个线程执行时,这个模块的精度都是4。

还可以设置局部范围的精度,局部表示退出了这个范围就失效了。使用with/as语句可以设置局部精度,所以退出with/as语句块精度的设置就失效了。

>>> 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')     # 因为前面设置了全局精度为4

10.分数(Fraction)

分数模块fractions下的函数Fraction(),可以构建分数,分数和浮点数不同,分数是精确的。

同样地,如果工作中没有特殊需求研究分数,这里可以不用细究。

例如,构建分数三分之一。

>>> import fractions
>>> fractions.Fraction(1,3)
Fraction(1, 3)

还可以根据浮点数的字符串格式构建分数。

>>> fractions.Fraction('0.3')
Fraction(3, 10)

然后可以用分数进行运算。

分数加整数:

>>> fractions.Fraction(1,3) + 1
Fraction(4, 3)

分数加、减、乘、除分数:

>>> fractions.Fraction(1,3) + fractions.Fraction(2,3)
Fraction(1, 1)
>>> fractions.Fraction(1,3) - fractions.Fraction(2,3)
Fraction(-1, 3)
>>> fractions.Fraction(1,3) * fractions.Fraction(2,3)
Fraction(2, 9)
>>> fractions.Fraction(1,3) / fractions.Fraction(2,3)
Fraction(1, 2)

另外,float对象有一个as_integer_ratio()函数,可以将浮点数转换成整数的元组表示形式,然后根据这个元组就可以构造出分数来。例如,将2.5转换成元组,并进而转换成分数。

>>> (2.5).as_integer_ratio()
(5, 2)      # 得到元组

>>> fractions.Fraction(*(2.5).as_integer_ratio())
Fraction(5, 2)

二、练习

数据类型识别

请直接说出下列数据的类型

1. 4343
2. 43.53
3. 0.0
4. 43.
5. 0

记住你的答案,然后在交互式解释器中验证自己的答案,type(x)函数用来返回参数x的类型

>>> type(4343)
<class 'int'>
>>> type(43.53)
<class 'float'>
>>> type(0.0)
<class 'float'>
>>> type(43.)
<class 'float'>
>>> type(0)
<class 'int'>

数据类型转换

请直接说出下列代码的执行结果

1. int(3.14)
2. float(3)
3. int(float(3))
4. float(int(3.14))

记住你的答案,然后在交互式解释器中验证自己的答案

>>> int(3.14)
3
>>> float(3)
3.0
>>> int(float(3))
3
>>> float(int(3.14))
3.0