IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 字符串公式四则运算求值 -> 正文阅读

[Python知识库]字符串公式四则运算求值

事先说明

python中已经有eval() 函数用于实现字符串公式求值功能。
看了一点《编译原理》,突然有了想实现这么一个功能的想法!(之前也尝试过,但没有成功写出代码)

本文求解

仅支持四则运算 { + , ? , ? , / } \{+, -, *, /\} {+,?,?,/}和括号{(,)},且忽略空格的影响。如果想支持幂运算等操作也可自己弄懂代码之后自行添加。本代码已经经过某些公式字符串的验证,并且能成功求解。如若大家发现bug,可与我联系。

词分析

例如 " 1 + 28 ? ( 2 + 5 ) / 5 ? 114 / ( 100 + 200 ? 100 ) ? 3343 / 323 " "1 + 28 * (2 + 5 ) / 5 * 114 / (100 + 200 - 100) * 3343 / 323" "1+28?(2+5)/5?114/(100+200?100)?3343/323"。因为它是一个个字符组成的,我首先将它合成一个个操作符或者数字。输出如下:
[ ′ 1 ′ , ′ + ′ , ′ 2 8 ′ , ′ ? ′ , [ ′ 2 ′ , ′ + ′ , ′ 5 ′ ] , ′ / ′ , ′ 5 ′ , ′ ? ′ , ′ 11 4 ′ , ′ / ′ , [ ′ 10 0 ′ , ′ + ′ , ′ 20 0 ′ , ′ ? ′ , ′ 10 0 ′ ] , ′ ? ′ , ′ 334 3 ′ , ′ / ′ , ′ 32 3 ′ ] ['1', '+', '28', '*', ['2', '+', '5'], '/', '5', '*', '114', '/', ['100', '+', '200', '-', '100'], '*', '3343', '/', '323'] [1,+,28,?,[2,+,5],/,5,?,114,/,[100,+,200,?,100],?,3343,/,323]

解析树

根据“词分析”的生成解析树的形式,结果返回解析树的根节点。

后序优先遍历

根据生成的解析树,采用后序优先遍历求解。

代码Code

from collections import deque

class Node:
    def __init__(self, operator, value):
        self.operator = operator
        self.value = value
        self.lchild = None
        self.rchild = None

def operator_(operator, left, right):
    if operator == "+":
        return left + right
    if operator == "-":
        return left - right
    if operator == "*":
        return left * right
    if operator == "/":
        return left / right

def postOrder(node, deque):
    if node == None:
        return
    postOrder(node.lchild, deque)
    postOrder(node.rchild, deque)
    if node.operator:
        right = deque.pop()
        left = deque.pop()
        deque.append(operator_(node.value, left, right))
    else:
        deque.append(node.value)

class Formula:
    def __init__(self, formula_str):
        self.formula_str = formula_str
        self.node = None
        self.operator = ["+", "-", "*", "/"]
        self.prior = ["*", "/"]
        self.noprior = ["+", "-"]
        self.neglect = [" "]
        self.word_list = self.word_analyse(self.formula_str)

    # 返回一个个词
    def word_analyse(self, process_str):
        word_list = []
        if process_str == "":
            return word_list
        start = 0
        while start < len(process_str):
            #print(word_list)
            c = process_str[start]
            if c in self.operator:
                word_list.append(c)
                start += 1
            elif c == "(":
                end = start + 1
                count = 1
                while end < len(process_str) and count != 0:
                    if process_str[end] == "(":
                        count += 1
                    elif process_str[end] == ")":
                        count -= 1
                    end += 1
                if count != 0:
                    raise SyntaxError("正反括号不匹配")
                word_list.append(Formula.word_analyse(self, process_str[start + 1: end - 1]))
                start = end + 1
            elif c.isdigit():
                digit_c = ""
                while start < len(process_str) and process_str[start].isdigit():
                    digit_c += process_str[start]
                    start += 1
                word_list.append(digit_c)
            elif c in self.neglect:
                start += 1
            else:
                raise SyntaxError("表达式错误")
        return word_list

    # 返回解析树的根节点
    def sentence_analyse(self, word_list):
        root_node = None
        if len(word_list) == 0:
            return root_node
        index = 0
        while index < len(word_list):
            word = word_list[index]
            if word in self.operator:
                node = Node(True, word)
                if root_node == None:
                    raise SyntaxError("表达式错误")
                node.lchild = root_node
                if word in self.noprior:
                    end = index + 1
                    while end < len(word_list) and word_list[end] not in self.noprior:
                        end += 1
                    if index + 1 == end:
                         raise SyntaxError("表达式错误")
                    node.rchild = Formula.sentence_analyse(self, word_list[index + 1: end])
                    index = end
                    root_node = node
                elif word in self.prior:
                    index += 1
                    if index == len(word_list):
                        raise SyntaxError("表达式错误")
                    node.rchild = Formula.sentence_analyse(self, word_list[index:index+1])
                    root_node = node
                    index += 1
            elif isinstance(word, list):
                root_node = Formula.sentence_analyse(self, word)
                index += 1
            else:
                if root_node != None:
                    raise SyntaxError("表达式错误")
                root_node = Node(False, float(word))
                index += 1
        return root_node

    # 根据解析树求解字符串公式(后序优先遍历)
    def calu_formula_str(self):
        root_node = self.sentence_analyse(self.word_analyse(self.formula_str))
        deque_ = deque([])
        postOrder(root_node, deque_)
        return deque_.pop()


if __name__ == "__main__":
    formula = Formula("1 + 28 * (2 + 5  ) /  5 * 114 / (100 + 200 - 100) * 3343 / 323")
    print(formula.word_analyse(formula.formula_str))
    print(formula.calu_formula_str())
    # print(formula.word_list)
    # formula.calu_formula_str()
    # with open("question.txt", encoding="utf8") as f:
    #     for line in f.readlines():
    #         formula = line.split(".")[-1].split("=")[0].replace("×", "*").replace("–", "-").replace("÷", "/")
    #         print(formula)
    #         print(eval(formula) == Formula(formula).calu_formula_str())

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-30 12:01:04  更:2021-08-30 12:01:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:45:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码