输入逻辑表达式,输出真值表,支持六个基本逻辑运算

最终效果:

    输入合适公式(没有考虑优先级,只根据括号优先),输出时会提取其中的元素(比如这里有A B C),并打印真值表

 算法思路

求值的一般顺序是:带入每个元素的值,求出式子的真值,所以可以分为两块:1.枚举元素值(枚举) 2.根据元素值求式子值(计算

我认为这个的难点在于枚举,我们既要想办法提取出每一个元素,又要为其赋值(0和1)

我们先约定好六个运算符

'''
否.......... !(非)
合取........ &(与)
可兼或...... |(或)
不可兼或.... #
由...可得... >
当且仅当.... =
'''

并封装好这个真值表打印器 

class FindTruth:'''构造函数'''def __init__(self):'''输入'''def __In(self):'''枚举'''def __Count(self, i):'''计算公式结果'''def __Sum(self, Str):'''配对左右括号'''def __Pei(self, cur, Str):'''运算操作符'''def __Add(self, w, a, b = -1):'''输出'''def __Out(self):

 一,首先处理枚举:

对于提取元素:涉及到字符串的处理以及查重,python提供了便捷的set集合来处理

对于赋值:比如式子A|B|C,提取出ABC后,一共有从000 到 111,2^3种情况,而N个元素就有2^N种情况,显然是不能用简单的循环是实现的,这里可以用递归来处理

  a.利用set提取元素  

set(字符串)能把字符串里每个字符提取出来,构成一个集合,而集合是不存在相同字符的,所以这里完成了筛选重复字符的工作。

如set('A|B&C') = {'A', 'B', 'C', '|', '&'}

seta.difference(setb)能让seta留下于setb集合中不同的元素。

所以第二句生成了一个筛选掉运算符的元素集合,完成了元素的提取

def __In(self):#得到表达式Strself.Str = input("input your expression: \n")#筛出字母集合self.Set = set(self.Str).difference(set("()!&|>=#"))

b.利用递归枚举赋值

            如何递归呢,这里假如有三个元素A,B,C

递归函数有一个参数 i ,用来指定此次因该枚举哪一个元素的值,比如 i = 0, 则枚举A的值。

首先初始化一个字典用来存储元素的值:self.dict = {'A':0, 'B':0, 'C': 0}

           第一次:{'A':0, 'B':0, 'C': 0},i = 1,所以先分别给A赋值0和赋值1,并把 i 加一,再调用枚举函数(也就是递归调用自己)。因为要调用自己两次,这里就产生了1*2 = 2个分支:

分支1:{'A':0, 'B':0, 'C': 0},i = 1

分支2:{'A':1, 'B':0, 'C': 0},i = 1

           第二次,i = 1,分别给B赋值0和1,在第一次的两个分支的基础上产生了2*2 = 4个分支

分支1:{'A':0, 'B':0, 'C': 0},i = 1

分支11:{'A':0, 'B':0, 'C': 0},i = 2

分支12:{'A':0, 'B':1, 'C': 0},i = 2

分支2:{'A':1, 'B':0, 'C': 0},i = 1

分支21:{'A':1, 'B':0, 'C': 0},i = 2

分支22:{'A':1, 'B':1, 'C': 0},i = 2

           第三次,同理,给C赋值的时候,会产生总共4*2 = 8个分支,这时候递归枚举也结束了,我们也得到了八个枚举的结果

A B C
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

实现代码:

def __Count(self, i):'''结束条件:若最后一个元素也完成了枚举,则 打印 + 运算 '''if i == len(self.Lis):S = ''for l in self.Lis:S = S + str(self.Dic[l]) + ' 'print(S,self.__Sum(self.Str))#调用self__Sum()函数进行运算return'''不是结尾,则赋值并调用自己,产生两个分支'''self.Dic[self.Lis[i]] = 0self.__Count(i+1)self.Dic[self.Lis[i]] = 1self.__Count(i+1)

二,再来处理计算 __Sum(self, Str)

计算的思路很简单,我们分别设置三个值:

s :用来存储当前的终值,初始值设置为-1

s0 :用来存储当前式子或元素的值

operater :用来存储目前的操作符

然后一个字符一个字符地循环遍历表达式:

例:str = 'A | (A & B) & C'   调用 __sum(self, str):

循环1:字符 = 'A",则s = A的值

循环2:字符 = '|',则operater = '|'

循环3:字符 = '(',则s0 = __sum(self, ’括号内的那坨表达式‘),(这样便可利用递归简单地完成括号的处理)

s = (s operator s0),s0 = -1(更新s的值)

.......

到最后一个字符结束后,式子的值已经存储于s中了。

实现代码:

#求公式结果
def __Sum(self, Str):i = 0 #字符位置s = -1#式子真值while i < len(Str):c = Str[i]#单操作符'!'要做特殊的分类处理if c == "!":#右边是字母if Str[i+1] in self.Set:c = Str[i+1]i = i + 1s0 = self.__Add('!',self.Dic[c])   #右边是左括号else:end = self.__Pei(i+1, Str)s0 = self.__Add('!', self.__Sum(Str[i+1:end+1]))i = end#字母elif c in self.Set:s0 = self.Dic[c]#其它运算符elif c in set("&|>=#"):operat = c#左括号elif c == '(':end = self.__Pei(i, Str)s0 = self.__Sum(Str[i+1:end])i = end#运算结果if s == -1:s = s0s0 = -1elif operat != 0 and s0 != -1:s1 = ss = self.__Add(operat, s, s0)operat = 0s0 = -1i = i + 1return s
#配对左右括号
def __Pei(self, cur, Str):kflag = 1  # 左括号的数目while not kflag == 0:cur = cur + 1if Str[cur] == '(':kflag = kflag + 1elif Str[cur] == ')':kflag = kflag - 1return cur
#运算操作
def __Add(self, operator, a, b = -1):#b默认为-1时,表示是单操作符号' ! 'if operator == '!':boo = not aelif operator == '&':boo = a and belif operator == '|':boo = a or belif operator == '#':boo = ((not a) or (not b)) and (a or b)elif operator == '>':boo = (not a) or belif operator == '=':boo = ((not a) and (not b)) or (a and b)else:print("there is no such operator")if boo:return 1else:return 0

完整代码:

# -*- coding: utf-8 -*-
'''
否.......... !
合取........ &
可兼或...... |
不可兼或.... #
由...可得... >
当且仅当.... =
'''
class FindTruth:def __init__(self):#存储字母及其真值self.Dic = {}self.Lis = []#输入表达式self.__In()#输出真值表self.__Out()#输入def __In(self):#得到表达式Strself.Str = input("input your expression: \n")#筛出字母集合self.Set = set(self.Str).difference(set("()!&|>=#"))#求公式结果def __Sum(self, Str):i = 0 #字符位置s = -1#式子真值while i < len(Str):c = Str[i]#单操作符'!'要做特殊的分类处理if c == "!":#右边是字母if Str[i+1] in self.Set:c = Str[i+1]i = i + 1s0 = self.__Add('!',self.Dic[c])   #右边是左括号else:end = self.__Pei(i+1, Str)s0 = self.__Add('!', self.__Sum(Str[i+1:end+1]))i = end#字母elif c in self.Set:s0 = self.Dic[c]#其它运算符elif c in set("&|>=#"):operat = c#左括号elif c == '(':end = self.__Pei(i, Str)s0 = self.__Sum(Str[i+1:end])i = end#运算结果if s == -1:s = s0s0 = -1elif operat != 0 and s0 != -1:s1 = ss = self.__Add(operat, s, s0)operat = 0s0 = -1i = i + 1return s#配对左右括号def __Pei(self, cur, Str):kflag = 1  # 左括号的数目while not kflag == 0:cur = cur + 1if Str[cur] == '(':kflag = kflag + 1elif Str[cur] == ')':kflag = kflag - 1return cur    #运算操作def __Add(self, operator, a, b = -1):#b默认为-1时,表示是单操作符号' ! 'if operator == '!':boo = not aelif operator == '&':boo = a and belif operator == '|':boo = a or belif operator == '#':boo = ((not a) or (not b)) and (a or b)elif operator == '>':boo = (not a) or belif operator == '=':boo = ((not a) and (not b)) or (a and b)else:print("there is no such operator")if boo:return 1else:return 0#输出def __Out(self):#将字母放入dict和ListS = ''for c in self.Set:self.Dic[c] = 0self.Lis.append(c)S = S + c + ' 'print(S, self.Str)self.__Count(0)#构造2^n的序列def __Count(self, i):#是结尾,打印 + 运算if i == len(self.Lis):S = ''for l in self.Lis:S = S + str(self.Dic[l]) + ' 'print(S,self.__Sum(self.Str))return#不是结尾,递归赋值self.Dic[self.Lis[i]] = 0self.__Count(i+1)self.Dic[self.Lis[i]] = 1self.__Count(i+1)if __name__ == '__main__':F = FindTruth()

python - 根据表达式打印真值表相关推荐

  1. python正则表达

    http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html 要匹配一个模式,前后的数字块是相同的,中间是字母,比如111aadf111 这就 ...

  2. python中的递归思想_使用python语言表达分形与递归

    Fibonacci数列 Fibonacci数列是一个很有趣的结构,每后一项都等于前两项之和.它的前几位如下:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 134.. ...

  3. python整除表达 mod_[零基础学python]啰嗦的除法

    除法啰嗦的,不仅是python. 整数除以整数 看官请在启动idle之后,练习下面的运算: >>> 2/5 0 >>> 2.0/5 0.4 >>> ...

  4. python正则表达regex_Python 正则表达式(RegEx)

    版权所有,未经许可,禁止转载 正则表达式是组成搜索模式的字符序列. 正则表达式用于按指定的搜索模式搜索字符串. 正则表达式(RegEx)模块 Python有一个名为re的内置包,用来处理正则表达式. ...

  5. python代码表达失恋_Python 经典面试题汇总之网络篇

    网络篇 1.简述 OSI 七层协议 物理层:定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质. 数据链路层:定义如何传输格式化数据,以及如何访问物理介质. 网络层:定义逻辑网络地址. ...

  6. python代码表达元旦节_2020元旦的python学习

    效率好低今天(我爱屁股,毕竟今天好歹爬上黄金了hhh) 总结一下今天学的东西吧 + 加 - 减 * 乘 / 除 // 整除(取商) % 取余 ** 指数(x**y=xy ) 1.+可以用来连接多个字符 ...

  7. python 正则表达函数_python笔记-正则表达式常用函数

    1.re.findall()函数 语法:re.findall(pattern,string,flags=0) --> list(列表) 列出字符串中模式的所有匹配项,并作为一个列表返回.如果无匹 ...

  8. python怎么表达我喜欢你_如何用含蓄的话表达我喜欢你 含蓄表达我喜欢你的句子大全...

    有的时候,一句简单的我喜欢你,总是很难讲出来,有时喜欢可以不用直接表达出来,含蓄的表达方法也让人很心动,那么,如何用含蓄的话表达我喜欢你?下面八宝网小编就带来含蓄表达我喜欢你的句子大全. 如何用含蓄的 ...

  9. TouchDesigner常用python语句表达

    Derivative TouchDesigner 是一款基于3D动画和VFX的实时节点的图形生成器.它是一种基于节点的可视化编程语言,它以节点形式构建视觉网络,并集成了许多交互设备组件.TouchDe ...

最新文章

  1. 基于SSM实现在校学生考试系统
  2. POJ 1293 - Duty Free Shop 01背包记录所选物品
  3. linux下watch常见用法,watch命令详解(linux)
  4. 关于目录操作walk
  5. PHP配置限制文件大小上传
  6. 终于解决H3C交换机reset saved-configuration后不能启动的问题
  7. js中递归调用返回值为undefined问题
  8. 【分布式定时任务】定时任务实现几种方式
  9. phpcms 文件:index.html 不可写,phpcms uploadfile不可写怎么办
  10. 用 Amazon Web Services 进行云计算,第 3 部分:用 EC2 根据需要提供服务器
  11. 手把手教你刷github提交记录
  12. “双减”政策下的少儿编程市场:前8月融资12起,资本加持下何时跑出“独角兽”?...
  13. C语言课设——宿舍管理
  14. ITU BT 601建议及与ITU BT656 的区别
  15. 看不懂Offer上的岗位?这一篇统统给你说明白!
  16. crontab shell 每5秒执行_linux定时任务crontab 实现每秒执行一次的方法
  17. 计算机毕业设计开题报告(电商网站类)模板
  18. 关于PPP拨号 和 AT指令实现GPRS模块联网的疑问
  19. 抓住屌丝心理才是王道
  20. Lr CC使用几何面板中的直立控件调整图片教程

热门文章

  1. 一名大学毕业生的心酸求职历程全记录
  2. C语言:结构体和共用体
  3. threejs 绘制球体_【webGl】threejs实现一个简单的动画-弹跳的小球
  4. 域名解析的详细内部过程
  5. 深圳周边你还不知道的团队建设活动好地方-深圳公司团建好地方推荐
  6. Linux进阶(日志分割工具logrotate)
  7. 搭载了HarmonyOS 2的华为nova9,有哪些眼前一亮的功能?
  8. 联想电子商务案例分析
  9. C语言+easyX界面库实现贪吃蛇
  10. arduino uno电压_了解Arduino UNO电路