一、数值数据类型讲解
1.数值类型
Python 数值类型用于存储数字,支持多种数字类型,如整型、浮点型、复数等:
【1】整型(int),也就是整数,即不带小数部分的数字。
注意:Python3 中的整型数据没有大小限制,支持无穷精度,不再像Python2中还要区分为int和long类型。另外,布尔(bool)类型是整型的子类型,后面会讲。
整数除了十进制整数外,还可以写成二进制、八进制、十六进制甚至是其它进制的整数,常见的有:
-
当一个整数以
0b
或0B
开头,其后都是0、1时,默认识别为二进制整数,如0b10001(对应十进制17)。 -
当一个整数以
0o
或0O
开头(数值零和大、小写的字母o),其后都是0-7之间的数值时,默认识别为8进制整数,如0o123(对应十进制83)。 -
当一个整数以
0x
或0X
开始,其后都是[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