多进制计算器
小名在工作中经常碰到各种进制数据的四则计算,他决定要写一个程序来支持多进制计算,这个计算器要支持 + - * / ( ),另外可以设置进制来支持2-16进制的加减乘除 不考虑超大数场景。
输入参数有两个:
1.待计算的字符串,包含数字 + - * / ( ),待计算的字符串格式正确,不需要考虑非法字符、除索异常,数字符合下面参数的进制要求。涉及到a、b等字符统一小写;2、进制值,取值范围从2到16;
2. 进制值,取值范围从2到16;
注意:
1. 整数除法按截断除法处理(向0取整)
2. 表达式均为合法表达式,相同优先级计算时按从左到右方或进行
3. 表达式长度大于1,小于1000输出输出计算结果,
输出:
结果按对应进制输出,涉及到a、b等字符统一小写
例程都跑出来了
思路:
都将字符串整合成10进制,再使用lc772题 计算器方法进行计算,之后再整合回原始进制。
#--------------进制转换模块
def trans_map(cint):
# cint: int
# return: str
# 把数字转化为相应字符,比如10-a, 11-b
if cint < 0:
return None
elif cint < 10: # 数字转为字母
return str(cint)
elif cint >= 10: # ASCII码转为字母a-z
return chr(cint - 10 + 97)
def tenToAny(n, origin):
# n进制: int
# origin: int
# return: str
res = ''
while origin:
res = trans_map(origin % n) + res # 需要逆序
origin = origin // n # 一定要整除,不然除3会进入死循环
return res
def anyToTen(m, origin):
# m: int
# origin:str
# return: int
# 任意进制的数转换为10机制
# 直接利用int的自带功能
return int(str(origin), base = m) # origin必须是字符串啊
#--------------字符串拆分模块
def s_split(ss:str)->list: # 将ss拆分成list
res = []
symbol = ['(',')','+','-','*','/']
left = 0
right = 0
while right < len(ss):
if ss[right] in symbol:
# print(ss[left:right])
if ss[left:right] != '':
res.append(ss[left:right])
left = right
# print(ss[left],'left')
res.append(ss[left])
left += 1
right += 1
res.append(ss[left:right])
return res
#--------------多进制list转换成10进制字符串模块
def s_tr_s(s:str,m:int)->str:# 多进制字符串转换成10进制字符串
s_l = s_split(s)
# print(s_l)
if s_l[0] == '-':# case -3/4
s_l = ['0'] + s_l
for i in range(len(s_l)):
if s_l[i] not in ['(',')','+','-','*','/']:
s_l[i] = str(anyToTen(m,s_l[i]))
return ''.join(s_l)
#--------------计算器模块
def calculate(s: str) -> int:
stack_num = []
stack_opt = []
i = 0
priorty = {'(':0,')':0,'+':1,'-':1,'*':2,'/':2}
while i<len(s):
if s[i]==' ':
i += 1
continue
if '0'<=s[i]<='9':
j = i
while i+1<len(s) and '0'<=s[i+1]<='9':
i += 1
num = int(s[j:i+1])
stack_num.append(num)
elif s[i]=='(':
stack_opt.append(s[i])
elif s[i]==')':
while stack_opt[-1]!='(':
opt = stack_opt.pop()
A = stack_num.pop()
B = stack_num.pop()
res = calc(A,B,opt)
stack_num.append(res)
stack_opt.pop()
else:
while stack_opt and priorty[stack_opt[-1]]>=priorty[s[i]]:
opt = stack_opt.pop()
A = stack_num.pop()
B = stack_num.pop()
res = calc(A,B,opt)
stack_num.append(res)
stack_opt.append(s[i])
i += 1
while stack_opt:
opt = stack_opt.pop()
A = stack_num.pop()
B = stack_num.pop()
res = calc(A,B,opt)
stack_num.append(res)
return stack_num[-1]
def calc(num1,num2,opt):
if opt=='+':
return int(num1)+int(num2)
elif opt=='-':
return int(num2)-int(num1)
elif opt=='*':
return int(num2)*int(num1)
elif opt=='/':
return int(num2)//int(num1)
#---------------------------------------------
def main(ss,m):
ten_s = s_tr_s(ss,m)
# print(ten_s)
ans_ten = calculate(ten_s)
if m == 10:
print(ans_ten)
else:
ans = tenToAny(m, ans_ten)
print(ans)
if __name__ == '__main__':
ss = '(1-2)*3+4'
m = 10
main(ss,m)
ss = '-3/4'
m = 10
main(ss,m)
ss = '101+11'
m = 2
main(ss,m)
ss = 'af00+ff'
m = 16
main(ss,m)
四个样例的输出:
1
0
1000
afff