zoukankan      html  css  js  c++  java
  • 自动生成四则运算题目(python实现)

    自动生成四则运算题目(python实现)

    项目分析

    项目仓库: 地址

    需求

    1. 仅包含四则运算
    2. 结果不能为负数
    3. 数字大小在 100 以内
    4. 支持真分数运算

    设计实现过程及代码说明

    项目文件结构如下:

    模块 功能
    main.py 主函数(表达式生成, 表达式的求解)
    mainTest.py 测试函数(单元测试)

    1. 分析与设计

    本设计设计栈的使用, 逆波兰表达式(后缀表达式)

    表达式式生成

    仔细分析有如下特点:

    • 运算符的个数比运算数少一个
    • 被除数不能为 0

    具体实现步骤

    1. 利用 Python 的字符串来存储表达式
    2. 随机生成一个运算数
    3. 再随机选择一个四则运算符
    4. 重复步骤 1 和 2

    为了美观和操作方便, 表达式中运算符和运算数使用空格隔开

    求解表达式

    中缀表达式转换为后缀表达式, 再进行求值

    具体代码实现

    表达式生成代码

    
    def makeFormula(upperLimit=100, fraction=False) -> str:
        if fraction:
            upperLimit = 20
            count = randint(4, 8)
        else:
            count = randint(1, 3)
        build = ""
        number1 = randint(1, upperLimit)
        build += str(number1)
    
        for i in range(count):
            if fraction and (i+1) % 2:
                operation = 3
            elif fraction:
                operation = randint(1, 2)
            else:
                operation = randint(1, 3)
            number2 = randint(1, upperLimit)
            op = ' ' + OP[operation] + ' '
            build += op + str(number2)
    
        return build
    
    

    中缀表达式转换为后缀表达式

    
    def getPostfixExpression(infixExpr: str) -> List[str]:
        # 记录操作符优先级
        prec = {'*': 3, '/': 3, '+': 2, '-': 2, '(': 1}
        postfixList = []
        operatorStack = []
        # 以空格分割表达式, 并转为字符数组
        tokenList = infixExpr.split()
    
        # 中缀表达式转换为后缀表达式
        for token in tokenList:
            if token in "+-*/":
                while operatorStack and 
                        prec[operatorStack[-1]] >= prec[token]:
                    postfixList.append(operatorStack.pop())
                operatorStack.append(token)
            elif token == '(':
                operatorStack.append(token)
            elif token == ')':
                topToken = operatorStack.pop()
                while topToken != '(':
                    postfixList.append(topToken)
                    topToken = operatorStack.pop()
            else:
                postfixList.append(token)
        while operatorStack:
            postfixList.append(operatorStack.pop())
    
        return postfixList
    
    

    求解后缀表达式

    
    def solvingPostfixExpression(postfixList: List[str]):
        operandStack = []
    
        # 计算后缀表达式
        for token in postfixList:
            if token in "+-*/":
                operand2 = operandStack.pop()
                operand1 = operandStack.pop()
                try:
                    result = doMath(token, operand1, operand2)
                    operandStack.append(result)
                except:
                    return "ERROR: Dividend cannot be 0"
            else:
                operandStack.append(int(token))
    
        return operandStack.pop()
        
    def doMath(op: str, number1, number2):
        if op == '+':
            return number1 + number2
        elif op == '-':
            return number1 - number2
        elif op == '*':
            return number1 * number2
        else:
            return Fraction(number1, number2)
    
    

    项目测试

    主要使用 unittest 进行单元测试

    具体代码如下

    
    class MyTestCase(unittest.TestCase):
        def test_solvingPostfixExpression_valid(self):
            test = solvingPostfixExpression(
                ['3', '5', '/', '1', '6', '/', '-'])
            result = Fraction(13, 30)
            self.assertEqual(test, result)
    
            test = solvingPostfixExpression(
                ['3', '15', '*', '20', '4', '/', '-'])
            result = 40
            self.assertEqual(test, result)
    
        def test_solvingPostfixExpression_invalid(self):
            test = solvingPostfixExpression(['2', '0', '/'])
            result = "ERROR: Dividend cannot be 0"
            self.assertEqual(test, result)
    
            test = solvingPostfixExpression(
                ['6', '5', '10', '2', '/', '-', '/'])
            result = "ERROR: Dividend cannot be 0"
            self.assertEqual(test, result)
    
        def test_getPostfixExpression(self):
            test = getPostfixExpression("22 / 2")
            result = ["22", "2", "/"]
            self.assertEqual(test, result)
    
            test = getPostfixExpression("38 - 5 * 6")
            result = ['38', '5', '6', '*', '-']
            self.assertEqual(test, result)
    
            test = getPostfixExpression("( 16 - 9 ) * 6")
            result = ['16', '9', '-', '6', '*']
            self.assertEqual(test, result)
    
    
    if __name__ == '__main__':
        unittest.main()
    
    

    性能分析

    直接使用 Pycharm 自带的性能测试工具进行性能分析
    运行100万次的分析结果如下:

    项目运行结果截图

  • 相关阅读:
    C/C++程序员必须熟练应用的开源项目[转]
    VC中基于 Windows 的精确定时[转]
    语音增强算法的概述[转]
    语音增强 [转]
    [转]四款主流手机音乐播放器横评
    1个简单的Log
    [转]全方位对比 安卓手机音乐播放器推荐
    [转]4款手机音乐播放器对比
    一个简单的log
    音频和视频合并
  • 原文地址:https://www.cnblogs.com/justlikecode/p/13703205.html
Copyright © 2011-2022 走看看