小M的37进制数字相乘问题
问题描述
小M最近在学习37进制的表示方法。37进制使用的字符集是:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$",其中字符依次代表从0到36的数字。现在,给定两个37进制的数字aa和bb,请你计算它们的乘积并输出结果,结果也需使用37进制表示。
解题思路
-
字符到数字的转换:将37进制的字符转换为对应的整数值。
-
数字到字符的转换:在计算结果后,将整数值转换回37进制的字符。
-
乘法实现:将两个37进制的字符串转换为整数,进行乘法运算,然后将结果转换回37进制的字符串。
-
处理进位:处理10进制和37进制字符串之间的进位问题。
代码实现
字符到数字的转换
将37进制的字符转换为对应的整数值。可以使用字典来实现这个映射,具体代码如下:
char_to_int = {
'0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
'5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
'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, '$': 36
}
或者将上述代码简化为以下代码:
char_to_int = {char: idx for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}
简化后的代码使用了enumerate()函数辅助构建字典。该函数用于将一个可遍历的数据对象(如列表、元组或字符串,在此步骤中指37进制使用的字符组成的字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环当中。
上述代码还使用了for循环的简写操作,实际上等价于以下代码:
char_to_int = {}
for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$"):
char_to_int[char] = idx
数字到字符的转换
在计算结果后,将整数值转换回37进制的字符。同样可以使用字典来实现这个映射。具体代码如下:
int_to_char = {
0: '0', 1: '1', 2: '2', 3: '3', 4: '4',
5: '5', 6: '6', 7: '7', 8: '8', 9: '9',
10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F', 16: 'G',
17: 'H', 18: 'I', 19: 'J', 20: 'K', 21: 'L', 22: 'M', 23: 'N',
24: 'O', 25: 'P', 26: 'Q', 27: 'R', 28: 'S', 29: 'T', 30: 'U',
31: 'V', 32: 'W', 33: 'X', 34: 'Y', 35: 'Z', 36: '$'
}
或者将上述代码简化为以下代码:
int_to_char = {idx: char for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}
乘法实现
将两个37进制的字符串转换为整数,进行乘法运算,然后将结果转换回37进制的字符串。这里需要用到两个用于处理进位的自定义函数,分别命名为to_int和to_base37,这两个函数的具体内容稍后介绍。
int_a = to_int(a)
int_b = to_int(b)
product = int_a * int_b
return to_base37(product)
处理进位
在将结果转换回37进制字符串时,需要注意处理进位问题。这里需要定义上一步骤提到的两个自定义函数to_int和to_base37。
进制最基本的原理就是逢X进一位。以solution("ZZ", "X")为例,该测试用例实际上的运算过程如下:
ZZ(37) = 35 × 371 + 35 × 370 = 1330
X(37) = 33 × 370 = 33
1330 × 33 = 43890 = 32 × 372 + 2 × 371 + 8 × 370 = W28(37)
该步骤实际的思路,就是将这样的运算过程用编程语言表示。
-
37进制转10进制(
to_int函数)def to_int(s: str) -> int: num = 0 for char in s: num = num * 37 + char_to_int[char] return num该函数的实际原理是按权求和,即将37进制数按位权形式展开多项式和的形式,求其最后的和,就是其对应的十进制数。以37进制数字
ZZ为例,该数字各数位的数字和位权如下表:名称 十 个 数位 35 35 位权 371 370 因此,
to_int('ZZ')的实际运算方式如下:ZZ(37) = 35 × 371 + 35 × 370 = 1330
-
10进制转37进制(
to_base37函数)def to_base37(num: int) -> str: if num == 0: return "0" result = [] while num > 0: result.append(int_to_char[num % 37]) num //= 37 return ''.join(result[::-1]) #使用result[::-1]将取得的余数逆序排列该函数的实际原理是除X取余法,在此步骤中指用37连续除十进制数,直到商为0,逆序排列余数得到结果。以
to_base37(43890)为例,该函数的原理可以用下图表示:将取得的余数逆序排列,得到一个37进制的3位数,百位、十位和个位分别是
32、2和8。由于最右侧的32在字符集中所对应的字母是W,因此to_base37(43890)实际返回的结果是'W28'。
完整代码
def solution(a: str, b: str) -> str:
# write code here
char_to_int = {char: idx for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}
int_to_char = {idx: char for idx, char in enumerate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$")}
def to_int(s: str) -> int:
num = 0
for char in s:
num = num * 37 + char_to_int[char]
return num
def to_base37(num: int) -> str:
if num == 0:
return "0"
result = []
while num > 0:
result.append(int_to_char[num % 37])
num //= 37
return ''.join(result[::-1])
int_a = to_int(a)
int_b = to_int(b)
product = int_a * int_b
return to_base37(product)
if __name__ == '__main__':
print(solution("ZZ", "X") == 'V8') #实际输出结果为False
print(solution("A", "B") == '2$') #实际输出结果为True