进制转换的思考

539 阅读3分钟

写在前面

今天分享一道真实的面试题目。

题目是编码实现十进制到二进制的转换:

例如:

2 10
3 11

编码实现

python3 实现

def translate(num: int):
    result = []
    while num != 0:
        result.append(str(num % 2))
        num = num // 2

    return "".join(result[::-1])
 
print(translate(3)) # 11

思考进阶一

上面的代码很简答的实现了十进制到二进制的逻辑,现在需要实现 十进制到八进制的转换、十进制到十六进制的转换、二进制转十进制等等。

例如:十六进制转十进制

15 15
a 16
13 19

其实过程也很简单 只要替换除数就可以实现,下面基于python3实现

# 十六进制的数字映射
temp = {
    '10': 'a',
    '11': 'b',
    '12': 'c',
    '13': 'd',
    '14': 'd',
    '15': 'f'
}

# 翻转字典
temp_reverse = {v: k for k, v in temp.items()}


def translate1(num: int, extra: int) -> str:
    result = []
    while num != 0:
        result.append(str(num % extra))
        num = num // extra
    return "".join([temp.get(i, i) for i in result[::-1]])


def translate2(b: str, extra: int) -> int:
    result = 0
    for index, value in enumerate(b[::-1]):
        result += int(temp_reverse.get(value, value)) * extra ** index
    return result
    
# 结果验证 这里使用自带的 hex() 函数验证结果
for i in range(14, 20):
    b = translate1(i, 16)
    o = translate2(b, 16)
    print(hex(i)[2:], "".join(b), i, o)
    
# 结果
"""
e d 14 14
f f 15 15
10 10 16 16
11 11 17 17
12 12 18 18
13 13 19 19
"""

图解计算过程

image.png

对应的十进制转换二进制的过程其实就是除法取余数的过程(除数为对应的进制),如图使用倒除法记录余数,最后倒叙余数既得结果;反之 二进制转换成十进制的过程就是对应余数乘法的过程。

思考进阶二

需求:有序生成excel列类似 A B C … Z AA AB; 即传入一个数字生成对应的序列表示 例如: 26 -> Z, 27 -> AA;

解题思路:

  • 题目类似进制的转换 27进制的数据。
  • 不同的地方是不会 各个位数的取值范围可能不相同。
  • 通过获取商与余数转换对应的值。
def num2xls_col(idx):
    if idx < 1:
        raise ValueError("Index is too small")
    result = ""
    while idx != 0:
        idx, r = divmod(idx - 1, 26)
        result = chr(r + ord('A')) + result
    return result

# 验证结果
for num in range(1, 26 * 8):
    if num % 26 in [0, 1, 2, 25, 24]:
        print(num2xls_col(num), end=",")
    elif num % 26 == 3:
        print("...", end="")
# A,B,...X,Y,Z,AA,AB,...AX,AY,AZ,BA,BB,...BX,BY,BZ,CA,CB,...CX,CY,CZ,DA,DB,...DX,DY,DZ,EA,EB,...EX,EY,EZ,FA,FB,...FX,FY,FZ,GA,GB,...GX,GY,

看似是进制转化的问题,实践起来却有不太一样,不过本质上都是除法取余数 开始的版本实现是字典存储数字与字母的映射关系,巧用 ascii 码可能代码更加简单。

总结

  • 对于这种看似简单的题目一定要考虑边界,比如开始的例子就没有考虑到小于零的数字。
  • ascii 可以有效结果字母与数字的连续关系。
  • 希望你可以按照我的顺序一步步理解我的解题思路。
  • 类似的算法题一定要从简单的问题一步步思考,一步步总结。