将十进制转换成其它进制,是怎么进行的呢?下面来详细叙述一下:

先来看十进制的表示。举个例子,666 这个数字,我们的读法是 “6百6十6”,意味着它是由各个位数(百位、十位、个位)上的数字累加成的,写成式子,表示如下:
666=6×102+6×10+6
可以看出组成十进制数的各个数字恰好是右边式子(多项式)的系数。对于一般情况,给定任何一个十进制数 x,它可以写成如下公式:
x=an×10n+an1×10n1++a1×10+a0
即十进制数字 xanan1a1a0 的形式。

有了这个式子,那么我们转化成其它进制就好办了。

如果现在要把十进制转化成二进制,就是将上述式子右边的基数 (10n,10n1,,10,1) 换成 (2n,2n1,,2,1) 的基数,那么就有公式:
x=bn×2n+bn1×2n1++b1×2+a0
于是十进制 x 表示成二进制的形式就是 bnbn1b1b0 了。

现在的关键是怎么求取系数呢?答案是取余。什么意思?举个例子,十进制数字 456 要得到各个位数的系数怎么办?过程如下:
用 456 对 10 取余得到一个个位上的 6 (商为 45),
再用 45 对 10 取余得到一个十位上的 5(商为 4),
再用 4 对 10 取余得到一个百位上的 4(商为0)。
是不是很简单?

相似地,那么这个十进制数字 456 转换成二进制,就只需将对 10 取余换成对 2 取余就行了。过程如下:
先用数字 456 对 2 取余得到一个余数 0 (商为 228),
再用 228 对 2 取余得到一个余数 0(商为 114),
再用 114 对 2 取余得到一个余数 0(商为 57),
再用 57 对 2取余得到一个余数 1(商为28),
再用 28 对 2 取余得到一个余数 0(商为14),
再用 14 对 2 取余得到一个余数 0(商为 7),
再用 7 对 2 取余得到一个余数 1(商为 3),
再用 3 对 2 取余得到一个余数 1(商为1),
再用 1 对 2 取余得到一个余数 1(商为0)。
上述的所有余数就是二进制的各个位数上的系数,从后往前排列,得到 111001000,这个二进制数就是十进制数字 456 的二进制表示。

Python 代码如下:

def dec2bin(n):  # 注:输入的十进制 n>=0且为整数
    rest = []
	if n==0:
		return 0
    while(n>0):
        rest.append(str(n%2))  # 得到各个位数上的余数
        n = int(n/2)
    rest.reverse()  # 将余数从后往前排列
    return ''.join(rest) # 将列表形式转化成字符串形式输出

相应地,转换成八进制,就只需要将上述的 2 换成 8 就可以了。

Python 代码如下:

def dec2oct(n):  # 注:输入的十进制 n>=0且为整数
    rest = []
	if n==0:
		return 0
    while(n>0):
        rest.append(str(n%8))  # 得到各个位数上的余数
        n = int(n/8)
    rest.reverse()  # 将余数从后往前排列
    return ''.join(rest) # 将列表形式转化成字符串形式输出

但是转化成十六进制呢?那就不单单用上面的思路了!(还需要对余数进行处理!)

上面这句话什么意思呢?那我们要看十六进制的表示形式了。因为十六进制中有字符 ‘A’、‘B’、‘C’、‘D’、‘E’、‘F’,它们分别对应十进制中的 10、11、12、13、14、15。所以需要将这些字符与对应整数做一个映射才行,即先构建一个如下的映射:
1 —> 1, 2 —> 2, 3 —> 3, 4 —> 4, 5 —> 5,6 —> 6,
10 —> ‘A’, 11 —> ‘B’, 12 —> ‘C’, 13 —> ‘D’, 14 —> ‘E’, 15 —> ‘F’,
剩下的就跟之前一样了。

Python 代码如下:

def dec2hex(n):  # 注:输入的十进制 n>=0且为整数
    rest = []
    lists = list(map(chr, range(65,71)))  # 字符'A'、'B'、'C'、'D'、'E'、'F'
    lists = list(range(10))+lists
    nums = list(range(16))
    dicts = dict(zip(nums, lists))   #  构建映射
	if n==0:
		return dicts[n]
    while(n>0):
        rest.append(str(dicts[n%16]))
        n = int(n/16)
    rest.reverse()
    return ''.join(rest)

那么如果转化成更高的进制呢?比如说 26 进制?下面先来看个 Leetcode 上的一个关于将十进制转换成 26 进制的题目吧(Leetcode 168. Excel Sheet Column Title)。描述如下:

对于这个题目,跟之前做 “十进制转 16 进制” 的思路是一样的,唯一的不同是,余数为 0 的表示有点不一样。详细解释一下:
在十六进制中:
(0)10—> (0)16(1)10 —> (1)16(2)10 —> (2)16(15)10 —> (A)16(16)10 —> (11)16

可以看到,将十进制转换成十六进制时,当十六进制满十六才进了一位。十进制中是 “满十进一”,十六进制中是 “满十六进一”,那么自然而然就想到 26 进制中是 “满二十六进一”。但是,题目给出的条件是 (26)10 —> (Z)26,即 “满二十六并没有进一”。

有人会想,这会不会是 27 进制?答案肯定不会是,这明显是 26 进制(因为英文中只有 26 个字母啊)。那么,为什么 “满二十六并没有进一”?我们仔细来看一下,发现它并没有整数 0 对应的一项。上面是从整数 1 开始映射的,这就导致 26 也没有进位。

怎么解决上面的问题呢?有两种思路。

第一个是将映射区间向左平移一个单位,即用 0 来映射 ‘A’,那么,25 就会映射到 ‘Z’,26 就会映射到 ‘AA’(即此时有了 “满二十六进一”),剩下的就跟之前的 “十进制转十六进制” 一模一样了。在构造映射时,用 ‘0’ 映射到 ‘A’,用 ‘1’ 映射到 ‘B’,,用 ‘25’ 映射到 ‘Z’。为了满足题目要求,需要将输入的十进制整数 “减去1” 再进行映射。

Python 代码如下:

def dec2Title(n):  # 注:输入的十进制数 n为正整数
    m = n-1 # 先把数字向左平移一个单位
    rest = []
    letters = list(map(chr, range(65,91)))
    nums = list(range(26))
    dicts = dict(zip(nums, letters))       # 构建映射
    if m==0:
        return dicts[m]
    while(m>=0):  # 由于下面的商左移了,此处条件需要包含 “=” 情况
        rest.append(str(dicts[m%26]))
        m = int(m/26)-1  # 左移一个单位
    rest.reverse()
    return ''.join(rest)

第二个思路是将 26 —> ‘Z’ 换成 ‘0’ —> ‘Z’(相当于 “满二十六归零”),这样就有了余数为 0 的情况了。但是只做这个转换还不够,比如说,十进制数 26 转化后的正确形式应该是 ‘Z’,但是由于将 ‘Z’ 当作进位制了(即 “满二十六归零”),按照上面的改动会得到 ‘AZ’ 的结果,即向前进位了个 ‘A’。现在需要处理的是:不要它在 ‘Z’ 时进位。处理方法是:每当被整除时,将商减去 1 就可以了,如果没有被整除,那么商的计算公式不变。

Python 代码如下:

def dec2Title(n):  # 注:输入的十进制 n为正整数
    rest = []
    letters = [chr(90)]+list(map(chr, range(65,90)))
    nums = list(range(26))
    dicts = dict(zip(nums, letters))      # 构建映射
    while(n>0):
        rest.append(str(dicts[n%26]))
        n = int(n/26) if n%26!=0 else int(n/26)-1
    rest.reverse()
    return ''.join(rest)

有了上面这些不同进制的介绍,这样我们关于将十进制转化成任何进制都会觉得很容易了。如果需要将十进制转化成 K进制,此时的 K 若小于10,那么直接按照上面转二进制的方法就可以了(把代码中的 2 换作 K 即可);若 K 大于 10,则需要先建立映射表,当余数从 0 开始到 K-1 都有映射时(比如上面介绍的 16 进制),代码跟转二进制一样(只是多了个建立映射的步骤),当映射从 1开始到 K时,这种情况需要将它进行平移,或者对满进制做一个判断处理(比如上面介绍的 26 进制),其余就跟转二进制一样了。

======================================================

作者:哈哈村长
(转载请注明出处:https://blog.csdn.net/Deeven123/article/details/82942078)

10-05 10:59