菊厂221012第三题python

多进制计算器

小名在工作中经常碰到各种进制数据的四则计算,他决定要写一个程序来支持多进制计算,这个计算器要支持 + - * / ( ),另外可以设置进制来支持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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

deyiwang89

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值