Python入门(三):对象类型之数字

本文介绍了Python中的数字类型,包括整数、浮点数、分数和复数。讨论了不同进制的转换,浮点数的不精确性和复数的表示。还讲解了数字操作符,如逻辑运算、比较运算、算术运算和位运算,以及变量赋值和类型转换。

Python对象类型简介

  Python中,数据总是以对象的形式出现,而对象是内存中的一部分,是包含数值和相关操作的集合。本大章节主要介绍Python的内置对象,因为内置对象往往包括了表现问题领域的所有结构,并且Python的内置类型优化了用C实现的数据结构和算法,使得程序的编写更加方便,减少了内存部署、内存分配、实现搜索和读取等任务的编写。
  常见的内置对象类型有:数字、字符串、列表、字典、元组、文件、集合、其他类型、编程单元类型、与实现相关的类型等。 本小节将介绍数字类型。

数字

  Python不仅支持通常的数字类型,而且能够通过常量直接创建数字以及处理数字的表达式。Python数字类型的完整工具包括: 整数和浮点数、复数、固定精度的十进制数、有理分数、集合、布尔类型、无穷的整数精度以及各种数字内置函数和模块。

1.常见数字类型

1.1 整数和浮点数

  整数以十进制数字的字符串写法出现,浮点数带一个小数点或,也可以加上一个科学计数标志e或者E。如果编写一个带有小数点或幂的数字,Python将其变成一个浮点数对象,并且在表达式和运算中启用浮点数的运算法则。

#整数  1234, -24, 0, 11111111111
#浮点数  1.23, 3.1415, 2.7e8, 4E-10

整数的其他进制
  整数除了默认的十进制,还可以以二进制、八进制以及十六进制的形式出现。二进制数以0b开头,后接由数字0和1构成的字符串;八进制数以0o或者0O开头(0和小写或者大写的字母"o"),后接由数字0-7构成的字符串;十六进制数以0x或者0X开头,后接数字0-9和字母A-F。Python默认显示十进制数字,但这些进制可以相互转换。

num1=0b100    #二进制
num2=0o100    #八进制
num3=0x100    #十六进制
num4=100      #十进制
print("num1: %d, num2: %d, num3 %d, num4: %d." %(num1,num2,num3,num4))
#结果为:
num1: 4, num2: 64, num3 256, num4: 100.

十进制转换为其他进制:分别使用bin(I), oct(I)和hex(I)将十进制数I转换为二、八、十六进制。

number = 100
print ("bin of number is: ", bin(number))      #转换为二进制
print ("oct of number is: ", oct(number))      #转换为八进制
print ("hex of number is: ", hex(number))      #转换为十六进制

#结果为:
bin of number is:  0b1100100
oct of number is:  0o144
hex of number is:  0x64

其他进制转换为十进制,使用int(str, base). str为需要转换的数字的字符串,base是被转换数字的基底。例如,**int(‘100’, 2)**就是将二进制数字100转换为十进制数字,也就是4。因为有了后面的基底,进制前面的前缀可以省略。

print("the decimals of 100: %d" %int('100',2))
print ("the decimals of 0b100 : %d" %int('0b100',2))
print ("the decimals of 0o100 : %d" %int('0o100',8))
print ("the decimals of 0x100 : %d" %int('0x100',16))
#结果为:
the decimals of 100 : 4
the decimals of 0b100 : 4
the decimals of 0o100 : 64
the decimals of 0x100 : 256

浮点数
  主要说一下浮点数的表示问题。浮点数在计算机硬件中表示为二进制的小数:

0.125 = 1/10 + 2/100 + 5/1000

在计算机硬件中,只不过浮点数通过二进制存储:

0.125 = 0/2 + 0/4 + 0/8 

但是!!大部分十进制的数字都不能精确的表示为二进制的数据。因此,这导致在大多数情况下,你输入的十进制浮点数都只能近似地以二进制浮点数形式储存在计算机中。
例如,十进制的0.1,无法精确地表示为二进制的数字,二进制下,十进制的数字0.1是一个无限循环小数:

0.0001100110011001100110011001100110011001100110011...

因此,很多浮点数存储的值只是计算机表示的接近其本身的二进制分数。想要更美观的输出,我们可能会希望使用字符串格式化来产生限定长度的有效位数。**但是!这只是将真实的值进行了舍入再显示。**我们可以看一个简单的例子:

>>> 0.1+0.1+0.1==0.3
False

因为0.1无法在计算机内存中精确地表示出1/10,同样0.3也无法精确地表示出3/10. 因此逻辑判断为False.

  虽然浮点数运算有此问题,但是绝大多数情况下不必担心,只需要将最终的结果舍入为你期望的显示即可。精度的控制可以使用格式化输出,具体可以参见后面关于格式化输出的博文。
  如果想要精确表示十进制浮点数,可以使用decimal模块,或者fractions模块(该模块实现了基于有理数的算术运算)。此外,我们还可以使用Python提供的numpyScipy包进行精确的科学计算。
例如:float.as_integer_ratio() 可以将一个浮点数表示为分数。

>>> 0.1.as_integer_ratio()
(3602879701896397, 36028797018963968)

关于浮点运算的更多细节可以参见官方文档浮点算术:争议和限制

1.2 分数

  python的分数数字类型实现了一个有理数对象,保留一个分子和分母,避免了浮点数的一些不精确性和局限性。
python的fractions模块提供了对分数类型的支持。在fractions模块下,通过Fraction()函数构建分数,显示结果也是分数类型,而不是浮点数的形式。

>>> from fractions import Fraction
>>> x = Fraction(1,3)
>>> y = Fraction(4,6)
>>> x
Fraction(1, 3)
>>> y
Fraction(2, 3)
>>> x+y
Fraction(1, 1)

同样,分数也可以通过浮点数来创建,一种是上面提到的使用float.as_integer_ratio(),或者直接用Fraction(float)

>>> Fraction(1.5)
Fraction(3, 2)

有时候,浮点数转换为分数时,不可避免的仍然有精度损失,因为这个数在用浮点数形式表示的时候是不精确的,我们可以通过限制其分母的最大值来达到我们想要的精度:

>>> C= Fraction(1.33333)
>>> C
Fraction(6004784491161903, 4503599627370496)
>>> C.limit_denominator(10)      #限制分母最大值为10
Fraction(4, 3)

1.3 复数

  从外部来看Python的复数常写成实部+虚部的形式,虚部以j或者J结尾;从内部来看,复数都是通过一对浮点数来表示的,但操作按照复数的运算法则进行。我们也可以通过内置函数**complex(real, imag)**来创建复数:

>>> a=5+4j
>>> b=complex(3,4)
>>> a*b
(-1+32j)

  要从复数z中提取实部和虚部,分别使用z.realz.imag命令,从下面这个例子我们也再次看到,复数的内部是通过浮点数来表示的

>>> a = 4+5j
>>> a.real
4.0
>>> a.imag
5.0

再一个常用的就是复数的共轭了,使用 z.conjugate() 命令即可:

>>> a = 4+5j
>>> a.conjugate()
(4-5j)

1.4 内置数学工具和扩展

  除了常见的数值常量外,Python还提供了很多处理数字对象的工具,包括:
1). 表达式操作符 : +, -, , /, >>, **, &等
2). 内置数学函数: pow, abs, round, int, hex, bin等
3). 公用模块: random, math等

2.数字操作符和表达式

  我们对数字的处理主要通过上述的表达式、内置函数和一些模块来进行处理。本文主要介绍一些常见的数学表达式操作符。

2.1 变量基础

我们在开始基本的数学运算之前,需要将变量赋值。变量可以不声明类型,它在第一次赋值的时候被创建,赋值后才能运算,否则会出现报错。变量的赋值很简单,其实上面的例子已经表示出了这一概念,这里我们看几个小例子:

e.g.1 多个变量可以同时赋相同的值

>>> a=b=c=1
>>> a+b+c
3

e.g.2 多个变量可以同时赋不同的值

>>> a, b, c= 2, 3,'hello'
>>> a * b
6
>>> len(c)   #求字符串c的长度
5

2.2 基础表达式和操作符

2.2.1逻辑值检测和布尔运算

  任何对象都可以进行逻辑值检测,以便用于if等条件判断或作为布尔运算的操作数。一个对象在默认情况下一般为逻辑真,逻辑假的情况有:
1). 定义为假值的常量: None, False
2). 任何数值类型的0: 0, 0.0, 0j …
3). 空序列和多项集: ’ ', [], {}, set()

布尔运算描述
x or y如果x为真,返回True; 如果x为假,再执行y
x and y如果x为假,返回False; 如果x为真,再执行y
not x如果x为真,返回False;如果x为假,返回True

  提到运算,必定会有优先级,布尔运算中,优先级为:not > and > or,但是整个布尔运算的优先级低于比较运算,再低于算术运算。

2.2.2比较运算
比较运算描述
<严格小于
>严格大于
==等于
!=不等于
<=小于等于
>=大于等于
is对象标识
is not否定的对象标识

在这里简单说一下is 和 ==的区别:
1). is比较两个对象是否完全相同,它们是不是同一个对象,比较的条件为:内容(值)相同,内存地址相同
2). == 仅仅比较两个对象的值是否相同

a = 'hello'
b = a
print(a == b)
print(a is b)
print (id(a))  #id()函数显示内存地址
print (id(b))

######运行结果
True
True
140684554818872
140684554818872

可以看到,a,b变量的内存地址一样,因此 a is b 为真。Python中的直接赋值其实是一种引用,因此b=a是直接引用了 a的地址。 如果不是直接赋值,结果可能会不一样。想要进一步了解可以去看一下深拷贝和浅拷贝

a = ['hello','python','3.7']
b = a[:]
print(a == b)
print(a is b)
print (id(a))
print (id(b))
####运行结果
True
False
140333568416584
140333567555784

我们可以看到,b通过切片赋值,得到的值和a相同,但是内存的地址不同,也就是说,b指向了一个新的内存地址,并在此处分配内存给了其内容。

但是!Python会对一些小的整数对象 [-5,256] 或者简单的字符串对象进行缓存,使用的时候直接从缓存取出,所以不同的赋值也可能会出现is结果为真的情况,因为它们都指向了同一个缓存的地址。但是这种情况是针对交互式运算,IDE对此进行了优化

交互式:

>>> a=256
>>> b=256
>>> a is b
True
>>> a= 257
>>> b=257
>>> a is b
False
>>> a='hello'
>>> b='hello'
>>> a is b
True

IDE: 可以看到,IDE的优化,使得整数类型的缓存得到了扩大。

a = 'hello'
b = a[:]
c = 257
d = 257
print(a == b)
print(a is b)
print (id(a))
print (id(b))
print(c == d)
print(c is d)
print (id(c))
print (id(d))
####运行结果
True
True
139672846234992
139672846234992
True
True
139672834239824
139672834239824
2.2.3 算术运算

所有数字类型(复数除外)都支持下列算术运算操作,按优先级升序排序(所有数字运算的优先级都高于比较运算):

算术运算描述
x (+ - * /) y加减乘除四则运算
x // yfloor除法,x和y的商数,省略小数部分剩下的整数
x % yx除以y的余数
± xx不变或取反
abs(x)x的绝对值
int(x)将x转换为整数
float(x)将x转换为浮点数, x会被截断
divmod(x,y)返回x除以y的整数部分和余数(x//y, x%y)
x**y pow(x,y)x的y次幂,注意定义0的0次幂为1
round(x[,n])将x舍入到n位小数,n被省略时,返回整数; 注意半数值会舍入到偶数

关于半数值舍入到偶数

>>> round(5.5)
6
>>> round(2.5)
2

注意:操作符的优先级为:算术运算 > 比较运算 > 布尔运算

关于混合算术

  Python自动检测表达式的数字类型,运算符用于不同数字类型的操作数时,具有“较窄” 类型的操作数会被扩展为另一个操作数的类型,整数比浮点数更窄,浮点数又比复数更窄。可以通过下面的例子来理解:

整数与浮点数运算,结果升级为浮点数:

>>> a = 5
>>> b = 1.5
>>> type(a)
<class 'int'>
>>> type(b)
<class 'float'>
>>> a+b
6.5
>>> type(a+b)
<class 'float'>

浮点数与复数运算,结果升级为复数:

>> c = 1.5
>>> d = 2+3j
>>> type(c)
<class 'float'>
>>> type(d)
<class 'complex'>
>>> c+d
(3.5+3j)
>>> type(c+d)
<class 'complex'>
2.2.4 整数类型的位运算

位运算:只针对整数类型,把整数当做二进制位串进行操作

操作符(优先级依次增加)描述
x I y按位 计算
x ^ y按位 异或计算
x & y按位 计算
x << nx左移n位
x >> nx右移n位
~xx逐位取反

下面举几个简单的例子说明整数的位运算:

x = 1; 二进制为 0001
y = 2; 二进制为 0010
x | y = 0011 =3(十进制)   ##每一位数字按照或进行计算,在最后两位1或0都为1
x ^ y = 0011 =3(十进制)   ##异或运算规则是两个相异的数字进行异或计算,结果为1,相同的数字结果为0.
x & y = 0000 = 0(十进制)  ##最后两位1与0都为0
x << 2 = 0100 =4(十进制)  ## 将最后的1左移两位,其余用0补齐
x >> 2 = 0000 =0(十进制)  ##将最后的1右移两位,为0
~x = -2(十进制)           ##将x所有位取反

关于 ~1 = -2:
因为我们举例给的数字很小,因此上面的二进制串只列出了4位,但是对于运算和理解来说足够了。关于python3整数类型所占内存,可以参考博文 Python中对象的内存使用(一)
简单说明一下,1的二进制形式为:最后4位是0001, 前面可以补0,根据整数所占的字节数来补;全部取反后最后4位是1110,前面全部补1,我们知道,整数的二进制式最前面一位代表符号位,前面全部为1,代表为负数。计算机中所有的整数都是以补码的形式存储的,我们现在得到了取反后的负数的补码,将其转换为源码,符号位不变,其余位取反后+1,得到:符号为-,最后4位为0010,其余位全为0,因此最后的结果为-2.

以上就是python数字类型的基础笔记啦,欢迎各位指正提出意见~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值