在Python中,int()可用来把实数转换为整数,或者把数字字符串按指定进制转换为十进制数,详见文末的相关阅读。
然而,下面的代码又应该如何解释呢?
>>> int('0x10', 36)
42804
按照传统意义的解释,0x开头表示十六进制,而试图把十六进制数看作36进制数并转换为十进制数,上面的代码应该出错,但是却又没有出错。把'0x10'当作36进制,那么x又表示什么呢?执行下面的代码试试:
>>> import string
>>> for ch in string.ascii_lowercase:
print(ch, int(ch, 36))
a 10
b 11
c 12
d 13
e 14
f 15
g 16
h 17
i 18
j 19
k 20
l 21
m 22
n 23
o 24
p 25
q 26
r 27
s 28
t 29
u 30
v 31
w 32
x 33
y 34
z 35
看到这里,似乎应该想到了一个问题,Python的int()函数的第二个参数为啥要限制为0或2-36呢?上面的代码应该可以解释这个问题。对于N进制的数字,每一位上的数字应该介于0和N-1之间。
那么有没有可能利用字母f后面的字母来代表数字呢?这个问题一般不会有人去想,但是如果确实要这样做的话,是可以的。那就是g代表16,h代表17,i代表18,以此类推,x代表33,y代表34,z代表35。
>>> int('1m', 16)
Traceback (most recent call last):
File "<pyshell#61>", line 1, in <module>
int('1m', 16)
ValueError: invalid literal for int() with base 16: '1m'
>>> int('1m', 26)
48
>>> int('0ij', 16)
Traceback (most recent call last):
File "<pyshell#63>", line 1, in <module>
int('0ij', 16)
ValueError: invalid literal for int() with base 16: '0ij'
>>> int('0ij', 24)
451
>>> int('0ij', 25)
469
>>> 25*18 + 19
469
回到本文最初的问题, int('0x10', 36)的解释应该为:把字符串'0x10'看作36进制数并转换为十进制数,其中x代表数字33,并不表示十六进制数,那么 int('0x10', 36)等价于按权展开式0*36^3 + 33*36^2 + 1*36^1 + 0*36^0 = 42804。
>>> int('0x10', 36)
42804
>>> 33*36**2 + 1*36
42804
最后说明一下,对于int()函数,当第一个参数字符串隐含进制时,第二个参数必须为0,这一点仅适用于二进制、八进制、十六进制并且第二个参数指定的进制小于第一个参数字符串的隐含进制的情况,当第二个参数指定的进制大于第一个参数字符串中所有位字符表示的数字时,不存在这个限制。
>>> int('0b11', 0)
3
>>> int('0b11', 2)
3
>>> int('0b11', 16)
2833
>>> 16*16*11+16+1
2833
>>> int('0b11', 11)
Traceback (most recent call last):
File "<pyshell#70>", line 1, in <module>
int('0b11', 11)
ValueError: invalid literal for int() with base 11: '0b11'
>>> int('0b11', 12)
1597
>>> int('0o1', 25)
601