数值字面值
数值字面值有三种类型:整数、浮点数、虚数。没有复数字面值(复数由实数加虚数构成)。
注意:数值字面值不含正负号,即数值字面值都是非负数;实际上,负数(例如-1)是由一元运算符 '-' 和字面值(1)合成的。
(一)整数字面值有四种类型:十进制、二进制、八进制和十六进制。
(1)十进制整数字面值:非0整数由非0数字开头,跟着(如果有)由数字和分隔符(下划线“_”)构成的序列(不可以以分隔符结尾);整数0由一个或一个以上数字0跟着(如果有)由数字0和分隔符(下划线“_”)构成的序列(不可以以分隔符结尾)。注意:分隔符可选的而且不能相连。
>>>print("3_404_0678:",3_404_0678)
3_404_0678: 34040678
>>>print("00_000_0000:",00_000_0000)
00_000_0000: 0
练习题1:下面的代码有语法错误吗?
(A)print("1__2_45:", 1__2_45)
(B)print("0_9_00:", 0_9_00)
(C)print("12_48_:", 12_48_)
(D)print("0_0_00_:", 0_0_00_)
(2)二进制整数字面值:由“0b”或“0B”前导,后跟0、1和分隔符(下划线“_”)构成的序列(不可以以分隔符结尾)。
>>>print("0b_10_1:",0b_10_1)
0b_10_1: 5
>>>print("0B001_0100:",0B001_0100)
0B001_0100: 20
练习题2:下面的代码有语法错误吗?
(A)print("0b__01_0:", 0b__01_0)
(B)print("0_B_00:", 0_B_00)
(C)print("0b_012:", 0b_012)
(D)print("0b_0110_:", 0b_0110_)
(3)八进制整数字面值:由“0o”或“0O”前导,后跟0、1、2、3、4、5、6、7和分隔符(下划线“_”)构成的序列(不可以以分隔符结尾)。
>>>print("0o_107_156:",0o_107_156)
0o_107_156: 36462
>>>print("0O731_34:",0O731_34)
0O731_34: 30300
练习题3:下面的代码有语法错误吗?
(A)print("0o__72_0:", 0o__72_0)
(B)print("0_O_16:", 0_O_16)
(C)print("0o_0168:", 0o_0168)
(D)print("0o199_:", 0o199_)
(4)十六进制整数字面值:由“0x”或“0X”前导,后跟0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F、a、b、c、d、e、f和分隔符(下划线“_”)构成的序列(不可以以分隔符结尾),A(a)到F(f)分别代表10、11、12、13、14、15。
>>>print("0x_F8_A4:",0x_F8_A4)
0x_F8_A4: 63652
>>>print("0X7E1_3C:",0X7E1_3C)
0X7E1_3C: 516412
练习题4:下面的代码有语法错误吗?
(A)print("0x__7E2_0:", 0x__7E2_0)
(B)print("0_X_1F:", 0_X_1F)
(C)print("0x_016g:", 0x_016g)
(D)print("0x1Ef:", 0x1Ef)
(E)print("0X8CaE_:", 0X8CaE_)
整数字面值的长度没有限制,能一直大到占满可用内存。确定数值时,会忽略字面值中的下划线。下划线只是为了分组数字,让数字更易读。下划线可在数字之间,也可在 0x 等基数说明符后。注意,除了 0 以外,十进制整数字面值的开头不允许有零。也许你会觉得这一点不可思议,因为这与数学老师教的不一样。
这与整数字面值有2、8、10、16进制有关。Python采用双开关机制:首字符是“0”代表这个数是0、2进制数、8进制数或16进制数;第二个字符是“b”或“B”、“o”或“O”、“x”或“X”分别是2进制数、8进制数、16进制数,否则是0,后续不可以出现”0”和“_”之外的字符。下面讲到的浮点数字面值只有十进制,所以就没有这样的规定了。
(二)浮点数字面值有两种类型:十进制小数点形式和十进制指数形式。
浮点数的小数点“.”或指数标志“e”或“E”把浮点数分割为只有符号、数字和分隔符(下划线“_”)的1到3部分,这些部分忽略“+”或“-”后称作“数字部分(digitpart)”。数字部分由一个数字开头,后跟数字和分隔符组成的序列(不可以以分隔符结尾)。与整数十进制不同,浮点数最左边可以任意多个0。
(1)十进制小数点形式:用小数点(.)连接两个数字部分,如果整数部分(左部分)是0可以省略;如果小数部分(右部分)是0也可以省略;如果左右部分同时为0只可省略其中一个,因为两个都省略,剩下一个小数点就没意义了。
>>>print("002_34.0_5809:", 002_34.0_5809)
002_34.0_5809: 234.05809
>>>print(".12_045:", .12_045)
.12_045: 0.12045
>>>print("12_3.:", 12_3.)
12_3.: 123.0
练习题5:下面的代码有语法错误吗?
(A)print("1_.04:", 1_.04)
(B)print("1._123:", 1._123)
(C)print("13.1__45:", 13.1__45)
(D)print("0.0省略小数点前后的0:", .)
(2)十进制指数形式:由尾数(左侧)和指数(右侧)组成,指数由e或E,跟着正号“+”(可忽略)或负号“-”(不可忽略)后,再跟着数字部分;尾数可以是一个十进制小数点形式的浮点数,也可以是一个独立的可带符号数字部分——左边可以有任意多个0的整数(去除分割符后就是数学老师教的整数了)。
>>>print("002_34.0_5809e0_2:", 002_34.0_5809e0_2)
002_34.0_5809e0_2: 23405.809
>>>print(".12_045E-2:", .12_045E-2)
.12_045E-2: 0.0012045
>>>print("12_3.e0_1:", 12_3.e0_1)
12_3.e0_1: 1230.0
>>>print("-168e-2:", -168e-2)
-168e-2: -1.68
练习题6:下面的代码有语法错误吗?
(A)print("11_.e+2:", 11_.e+2)
(B)print("1.23e_3:", 1.23e_3)
(C)print("112Ee4:", 112Ee4)
(D)print("0x138E-0x2:", 0x138E-0x2)
(三)虚数字面值:由浮点数或可带符号的“数字部分(digitpart)”后添加“j”或“J”而成。
>>>print("002_34.0_5809J:", 002_34.0_5809J)
002_34.0_5809J: 234.05809j
>>>print(".12_045j:", .12_045j)
.12_045j: 0.12045j
>>>print("12_3.j:", 12_3.j)
12_3.j: 123j
>>>print("0.j:", 0.j)
0.j: 0j
>>>print("002_34.0_5809e0_2j:", 002_34.0_5809e0_2j)
002_34.0_5809e0_2j: 23405.809j
>>>print(".12_045E-2J:", .12_045E-2J)
.12_045E-2J: 0.0012045j
>>>print("12_3.e0_1j:", 12_3.e0_1j)
12_3.e0_1j: 1230j
>>>print("-168e-2j:", -168e-2j)
-168e-2j: (-0-1.68j)
练习题7:下面的代码有语法错误吗?
(A)print("8.2_23Je+2:", 8.2_23Je+2)
(B)print("1.23_j:", 1.23_j)
(C)print("12J.4_5:", 12J.4_5)
(D)print("0xABE-0xCj:", 0xABE-0xCj)
虚数字面值生成实部为 0.0 的复数。复数由一对浮点数表示,它们的取值范围相同。创建实部不为零的复数,则需添加一个浮点数,例如 (3.+4.j)。
数字类型
Python内置三种不同的数字类型:整数(int),类似于科学记数方法的浮点数(float) ,和复数(complex)。此外,布尔值属于整数的子类型。
Python对整数的精度不作限制。
浮点数通常使用C语言中的双精度浮点数(double)来实现,一个精度是32位,双精度就是64位。浮点数实际采用的精度可能与系统有关。你的电脑上浮点数的精度和内部表示法可在sys.float_info中查看。
程序代码(文本代码附录1):
运行结果:
属性浅解(选读内容):
max是可以表示最大的正浮点数,max_exp和max_10_exp分别为最大的正浮点数时二进制指数和10进制指数;同样,min是可以表示最小的正浮点数,min_exp和min_10_exp分别为最小的正浮点数时二进制指数和10进制指数。
mant_dig就是mantissa digits,即尾数位数,由于我们知道尾数的首位1是被隐藏的,所以真正的尾数位数共有52位小数位数加上首位的隐藏1,共有53位;dig表示可以保证被精确的转为浮点数的整数的数字个数,因为由mant_dig的值得到可以保证被精确的转为浮点数的整数小于等于9007199254740991,该数有16位数字,但是大于该数的16位数字的整数是无法被精确的转为浮点数的,所以能够被保证可以精确表示成64位浮点数的整数的最大位数是15。
epsilon是最小的大于1的浮点数(指数为0)和1之间的差值。即第52位是1,其它全0的浮点数(1/2^52=2.220446049250313e-16)。
radix表示基数,也就是进制数,radix=2表示二进制。
rounds表示的是当一个整数转成浮点数,对无法精确表示的整数的近似模式,这里为1表示的是取里原值最近的浮点表示,如果存在两种不同的表示距离一样近,那么取最后一位(即第52位bit)为0的情形。
复数包含实部和虚部,在Python中分别以一个浮点数表示。要从一个复数z中提取这两个部分,可使用z.real和z.imag。
另外标准库(非内置)包含附加的数字类型,如表示有理数的 fractions.Fraction 以及以用户定制精度表示浮点数的 decimal.Decimal。
数字可以由数字字面值、内置函数或运算的结果来创建的。不带修饰的整数字面值(包括十六进制、八进制和二进制数)会生成整数。包含小数点或幂运算符的数字字面值会生成浮点数。在数字字面值末尾加上 'j' 或 'J' 会生成虚数(实部为零的复数),你可以将其与整数或浮点数相加来得到具有实部和虚部的复数。
class int()函数
返回一个基于数字或字符串 x 构造的整数对象,一般用于将一个字符串或数字转换为整型。
调用方式1:无参数,int()。
返回整数0。
>>>print(int())
0
练习题8:运行下面的代码
>>>print(10/int())
(A)正常运行,打出计算结果。
(B)抛出SyntaxError异常。
(C)抛出ValueError异常。
(D)抛出NameError异常。
(E)抛出ZeroDivisionError异常。
(D)抛出TypeError异常。
调用方式2:浮点数参数,int(floatNum)。
向零舍入,返回整数。
>>>print(int(3.89))
3
>>>print(int(-3.89))
-3
练习题9:心算下面的代码的运行结果:
>>>print(int(-5.998)+int(1.199e1))
?
调用方式3:十进制整数字符串参数,int(intStr)。注:该字符串符合十进制整数字面值其他规范,并可以0开头。
把符合规范的字符串转为整数并返回它,否则抛出ValueError异常。
>>>print(int("1234"))
1234
>>>print(int("+1234"))
1234
>>>print(int("-1234"))
-1234
>>>print(int("01234"))
1234
>>>print(int("012_34"))
1234
练习题10:心算下面的代码的运行结果:
>>>print(int("-0_1_1_1") * int("-00_222"))
?
调用方式4:定义了 __int__()方法的对象参数,int(intObj)。
>>>class T:
... def __int__(self):
... return 1234
>>>print(int(T()))
1234
调用方式5:定义了 __index__()方法的对象参数,int(indexObj)。
>>>class T:
... def __index__(self):
... return 1234
>>>print(int(T()))
1234
调用方式6:定义了 _trunc__()方法的对象参数,int(truncObj)。
>>>class T:
... def __trunc__(self):
... return 1234
>>>print(int(T()))
1234
三方法优先级 __int__()>__index__()>__trunc__()。
>>>class T:
... def __trunc__(self):
... return 3
... def __index__(self):
... return 2
... #def __int__(self):
... # return 1
>>>print(int(T()))
2
>>>class T:
... def __trunc__(self):
... return 3
... def __index__(self):
... return 2
... def __int__(self):
... return 1
>>>print(int(T()))
1
练习题11:心算下面的代码的运行结果:
>>>class Test:
... def __trunc__(self):
... return 30
... def __int__(self):
... return 10
... def __index__(self):
... return 20
>>>print(int(Test()))
?
调用方式7:整数字符串参数(与进位制适配:a 到 z (或 A 到 Z )表示 10 到 35),自适应进位制,int(strNum, 0)或int(strNum, base=0)。
采用2、8、10和16进制的数字字面值规范检测字符串,转为整数返回,否则抛出ValueError异常。注意:对于十进制与方式3不同——除了0外,不可以0开头(整数字面值规范)。
>>>print(int("010",0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 0: '010'
>>>print(int("0b10",0))
2
>>>print(int("0o17",0))
15
>>>print(int("1_7_0",0))
170
>>>print(int("0x17",0))
23
>>>print(int("1A",0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 0: '1A'
练习题12:如果下面的代码不抛出异常,请心算运行结果:
>>>print(int("021",0))
?
>>>print(int("0b_10_1",0))
?
>>>print(int("0o2_6",0))
?
>>>print(int("2_7_01",0))
?
>>>print(int("0xFf",0))
?
>>>print(int("2E",0))
?
调用方式8:整数字符串参数(与进位制适配), 采用2、8、16进位制T,int(strNum, T)或int(strNum, base=T)。
与采用base=0的情况相似,不同的地方是字符串参数可以没有0b/0B、0o/0O、0x/0X前导。
>>>print(int("0b101",2))
5
>>>print(int("101",2))
5
>>>print(int("0o17",8))
15
>>>print(int("17",8))
15
>>>print(int("0x1F",16))
31
>>>print(int("1F",16))
31
练习题13:如果下面的代码不抛出异常,请心算运行结果:
>>>print(int("0B_1101",2))
?
>>>print(int("1101",2))
?
>>>print(int("0o25",8))
?
>>>print(int("25",8))
?
>>>print(int("0x25",16))
?
>>>print(int("25",16))
?
调用方式9:整数字符串参数(与进位制适配), 采用其它进位制T(3≤T≤7 or 9≤T≤15 or 17≤T≤36),int(strNum, T)或int(strNum, base=T)。
字符串参数中,不把0b/0B、0o/0O、0x/0X认为是前导,可以有1个或多个0的前导。
>>>print(int("0120_1",3))
46
>>>print(int("0x1F",36))
42819
>>>print(int("0001G",20))
36
注意:在所有的输入字符串参数的方式中,字符串的正号(+)或负号(-)与数字部分不可以有空格隔开,字符串两头的空格或换行符不影响转换。
例题:编写代码随机产生一个26进制的10位数,把它转为10进制和36进制,三种进制的三个数都打印出来,并打印验证36进制数。
程序代码(文本代码附录2):
运行结果:
练习题14:编写代码随机产生一个25进制的15位数,把它转为10进制和35进制,三种进制的三个数都打印出来,并打印验证35进制数。
附录1:
#浮点数精度测试
import sys
for k in str(sys.float_info).split(","):
print(k)
附录2:
#随机产生一个26进制的10位数,把它转为10进制和36进制,
#三种进制的三个数都打印出来,并打印验证36进制数。
from random import choice
#36进制数字集
dg36="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#26进制字符串,首字母非0
strNum26=choice(dg36[1:26])
#26进制数字集
dg26=dg36[:26]
#剩下的9位数
for i in range(9):
strNum26+=choice(dg26)
#打印26进制10位数字符串
print("26进制数:",strNum26)
#转为数字
num = int(strNum26,26)
#打印10进制数
print("10进制数:",num)
#转换为36进制
strNum36=""
while num>0:
subIndex = num % 36 #位下标
num//=36 #商
strNum36=dg36[subIndex] + strNum36
print("36进制数:",strNum36)
print("10进制数:",int(strNum36,36)) #验证