文章目录
前言
生活中一般大家使用的数字通常是用十进制(decimal system)表示,意味着
- 每一位数上满十,更高一位上数字加一,如9加1等于10
- 按权展开,第一位权为100, 第二位101 ……以此类推,第N位10(N-1),该数的数值等于每位的数值*该位对应的权值之和。
n u m b e r ( a N a N − 1 . . . a 1 ) ( 10 ) = ∑ i = 1 N a i ∗ 1 0 i − 1 = a N ∗ 1 0 N − 1 + a N − 1 ∗ 1 0 N − 2 + . . . + a 1 number(a_{N}a_{N-1}...a_{1})(10) = \sum_{i=1}^{N}a_{i}*10^{i-1} = a_{N} * 10^{N-1} +a_{N-1}*10^{N-2} + ...+ a_{1} number(aNaN−1...a1)(10)=∑i=1Nai∗10i−1=aN∗10N−1+aN−1∗10N−2+...+a1
而一些别的进制也存在于生活中,如时间秒和分之间是60进制(sexagesimal),计算机使用的是二进制(binary system),月和年是12进制(duodecimal number system),7天是1周,所以是7进制(septinary)。
如何将不同进制的数字进行转换呢? 这里分为三种情况:
- 将其余进制转位10进制
- 将10进制转为其余进制
- 其余进制之间互相转换
本文将介绍不同进制的转换的原理和如何使用python实现
一、将非10进制数转为10进制数
原理
这个是相对简单的,假设某X进制数,表示为number(X),则每个位数上可能有X个状态,从0到X-1。例如,
- 2进制下,数字为0,1,超过1则更高的数位上加1。如1的下一个数字是10(2)
- 12进制下,符号首先是普通的0到9,用A代表10,B代表11,超过11则更高的数位加1。如B(12)的下一个数字是10(12)
参考十进制的权重定义,在X进制下权为X,所以将数字转为10进制时
n
u
m
b
e
r
(
10
)
=
n
u
m
b
e
r
(
a
N
a
N
−
1
.
.
.
a
1
)
(
X
)
=
∑
i
=
1
N
a
i
∗
X
i
−
1
number(10) = number(a_{N}a_{N-1}...a_{1})(X) = \sum_{i=1}^{N}a_{i}*X^{i-1}
number(10)=number(aNaN−1...a1)(X)=i=1∑Nai∗Xi−1
=
a
N
∗
X
N
−
1
+
a
N
−
1
∗
X
N
−
2
+
.
.
.
+
a
1
= a_{N} * X^{N-1} +a_{N-1}*X^{N-2} + ...+ a_{1}
=aN∗XN−1+aN−1∗XN−2+...+a1
例如,将2AB(12)转为10进制,
n
u
m
b
e
r
(
10
)
=
2
A
B
(
12
)
=
2
∗
1
2
3
−
1
+
A
∗
1
2
2
−
1
+
B
∗
1
2
1
−
1
number(10) = 2AB(12)=2 * 12^{3-1} + A * 12 ^{2-1} +B*12^{1-1}
number(10)=2AB(12)=2∗123−1+A∗122−1+B∗121−1
A
(
12
)
=
10
(
10
)
,
B
(
12
)
=
11
(
10
)
A(12)=10(10),B(12) = 11(10)
A(12)=10(10),B(12)=11(10)
n
u
m
b
e
r
(
10
)
=
2
A
B
(
12
)
=
2
∗
1
2
2
+
10
∗
12
+
11
∗
1
=
419
(
1
)
number(10) = 2AB(12) = 2*12^{2} + 10*12+11*1=419(1)
number(10)=2AB(12)=2∗122+10∗12+11∗1=419(1)
python 实现
1. 不讲武德直接调用函数
int(x, base=10),int()函数的用法可以参考这个文章,此处简单介绍
参数
x – 字符串或数字。
base – 进制数,默认十进制。
- 当x是字符串时,则认为给定字符串对应的数字是base指定进制下的数字,然后再将其转换为十进制下的数字输出。若不输入base值时,base默认为10。字符串可能存在abc等英文字母代表相应进制下数字,不分大小写。a:10,b:11,以此类推。因此base最高为36,因为0到9共10个数,英文字母共26个。
int('10') #output:10
int('10', 12) #output:12,12进制下的10,是十进制下的12
int('1a', 12) #output:22
- 当x是数字时,后面不可加base,将float型小数数字转为10进制下整数int型,此处与主题无关
2. 手动实现int()
假设当出现高于10进制时候,使用的字符是英语字母a到z,不分大小写。假设给定的是合理的字符。
def int_self(num_str: str, base = 10):
# ord('0') = 48, ord('9') = 57,
# ord('a') = 97, ord('z') = 122,
# ord('A') = 65, ord('Z') = 90
n = len(num_str)
ans = 0
for i in range(n-1, -1, -1):
if 48 <= ord(num_str[i]) <= 57:
ans += int(num_str[i]) * base**(n - i - 1)
elif 97 <= ord(num_str[i]) <= 122 or 65 <= ord(num_str[i]) <= 90:
ans += (ord(num_str[i].lower()) - 97 + 10) * base**(n-i-1)
else:
return False #当有其他字符时候,报错
return ans
int_self('10', 12) # output: 12
二、将10进制数转为非10进制数
原理:
在上一个节已经知道
n
u
m
b
e
r
(
10
)
=
n
u
m
b
e
r
(
a
N
a
N
−
1
.
.
.
a
1
)
(
X
)
=
∑
i
=
1
N
a
i
∗
X
i
−
1
number(10) = number(a_{N}a_{N-1}...a_{1})(X) = \sum_{i=1}^{N}a_{i}*X^{i-1}
number(10)=number(aNaN−1...a1)(X)=i=1∑Nai∗Xi−1
=
a
N
∗
X
N
−
1
+
a
N
−
1
∗
X
N
−
2
+
.
.
.
+
a
1
= a_{N} * X^{N-1} +a_{N-1}*X^{N-2} + ...+ a_{1}
=aN∗XN−1+aN−1∗XN−2+...+a1
成立。现在需要将十进制下的数number(10)转化为 X进制下的数字
(
a
N
a
N
−
1
.
.
.
a
1
)
(
X
)
(a_{N}a_{N-1}...a_{1})(X)
(aNaN−1...a1)(X) 。
先观察式子, n u m b e r ( 10 ) = a N ∗ X N − 1 + a N − 1 ∗ X N − 2 + . . . + a 2 ∗ X 1 + a 1 number(10) = a_{N} * X^{N-1} +a_{N-1}*X^{N-2} + ...+ a_{2} * X^{1}+a_{1} number(10)=aN∗XN−1+aN−1∗XN−2+...+a2∗X1+a1,右边式子(RHS: right hand side)除以X,除了最后一项 a 1 a_{1} a1,其余项都含有X的次方,都可以整除X,而且 a 1 < X a_{1} < X a1<X,因此余数为 a 1 a_{1} a1,因此可以
- 用左边式子(LHS: left hand side)和右边式子(RHS)除以X的余数得 a 1 a_{1} a1。
- 然后将左边式子减
a
1
a_{1}
a1,然后除以X。此时
L H S = n u m b e r ( 10 ) − a 1 X LHS = \frac{number(10)-a_{1} }{X} LHS=Xnumber(10)−a1
R H S = a N ∗ X N − 2 + a N − 1 ∗ X N − 3 + . . . + a 2 RHS = a_{N} * X^{N-2} +a_{N-1}*X^{N-3} + ...+ a_{2} RHS=aN∗XN−2+aN−1∗XN−3+...+a2 - 跟求 a 1 a_{1} a1相同,重复1和2,可以依次从低位到高位,求得各数位上的数值 a i a_{i} ai
python 实现
因为十进制的数已知,因此使用整数int为格式进行输入,而X进制可能存在大于十的数,所以用字符串输出。但对于大于十进制的数,余数可能大于9,需要将其转换为对应英文字母。此处为简化,全转为小写。
def convertToBase(num: int, base: int) -> str:
if num == 0:
return "0"
negative = num < 0
num = abs(num)
digits = []
while num:
temp = num%base
if temp <10:
digits.append(str(num % base))
else:
# ord('a') = 97, ord('z') = 122,
temp_str = chr(temp - 10 + 97)
digits.append(temp_str)
num //= base
if negative:
digits.append('-')
return ''.join(reversed(digits))
convertToBase(22,12) # output: '1a'
三、其余进制之间互相转换
目前没有想到什么好办法,但可以根据上述部分,将初始值转为十进制,再将其转为要求进制下。
# num_str_input 为已知的字符串,base_input为初始进制值,
# temp_10为十进制数字,base_output为要求转为的进制值
# output为结果字符串
temp_10 = int(num_str_input, base_input)
output = convertToBase(temp_10, base_output)
output
总结
以上就是如何对进制进行转换的原理及python实现,基于数字0到9和26个英文字符(不分大小写),分别实现36进制以内的非十进制和十进制的转换。