日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

python - 根据表达式打印真值表

發(fā)布時(shí)間:2024/1/1 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python - 根据表达式打印真值表 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 輸入邏輯表達(dá)式,輸出真值表,支持六個(gè)基本邏輯運(yùn)算

最終效果

? ? 輸入合適公式(沒有考慮優(yōu)先級(jí),只根據(jù)括號(hào)優(yōu)先),輸出時(shí)會(huì)提取其中的元素(比如這里有A B C),并打印真值表

?算法思路

? ? 求值的一般順序是:帶入每個(gè)元素的值,求出式子的真值,所以可以分為兩塊:1.枚舉元素值(枚舉) 2.根據(jù)元素值求式子值(計(jì)算

? ? 我認(rèn)為這個(gè)的難點(diǎn)在于枚舉,我們既要想辦法提取出每一個(gè)元素,又要為其賦值(0和1)

? ? 我們先約定好六個(gè)運(yùn)算符

''' 否.......... !(非) 合取........ &(與) 可兼或...... |(或) 不可兼或.... # 由...可得... > 當(dāng)且僅當(dāng).... = '''

? ? 并封裝好這個(gè)真值表打印器?

class FindTruth:'''構(gòu)造函數(shù)'''def __init__(self):'''輸入'''def __In(self):'''枚舉'''def __Count(self, i):'''計(jì)算公式結(jié)果'''def __Sum(self, Str):'''配對(duì)左右括號(hào)'''def __Pei(self, cur, Str):'''運(yùn)算操作符'''def __Add(self, w, a, b = -1):'''輸出'''def __Out(self):

? ??一,首先處理枚舉:

? ??對(duì)于提取元素:涉及到字符串的處理以及查重,python提供了便捷的set集合來處理

? ? 對(duì)于賦值:比如式子A|B|C,提取出ABC后,一共有從000 到 111,2^3種情況,而N個(gè)元素就有2^N種情況,顯然是不能用簡單的循環(huán)是實(shí)現(xiàn)的,這里可以用遞歸來處理

? ? ? ? a.利用set提取元素??

? ? ? ? ? ? set(字符串)能把字符串里每個(gè)字符提取出來,構(gòu)成一個(gè)集合,而集合是不存在相同字符的,所以這里完成了篩選重復(fù)字符的工作。

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

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

? ? ? ? ? ? 所以第二句生成了一個(gè)篩選掉運(yùn)算符的元素集合,完成了元素的提取

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

? ? ? ? b.利用遞歸枚舉賦值

? ? ? ? ? ??如何遞歸呢,這里假如有三個(gè)元素A,B,C

? ? ? ? ? ? 遞歸函數(shù)有一個(gè)參數(shù) i ,用來指定此次因該枚舉哪一個(gè)元素的值,比如 i = 0, 則枚舉A的值。

? ? ? ? ? ? 首先初始化一個(gè)字典用來存儲(chǔ)元素的值:self.dict = {'A':0, 'B':0, 'C': 0}

?? ? ? ? ? ?第一次:{'A':0, 'B':0, 'C': 0},i = 1,所以先分別給A賦值0和賦值1,并把 i 加一,再調(diào)用枚舉函數(shù)(也就是遞歸調(diào)用自己)。因?yàn)橐?strong>調(diào)用自己兩次,這里就產(chǎn)生了1*2 = 2個(gè)分支:

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

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

?? ? ? ? ? ?第二次,i = 1,分別給B賦值0和1,在第一次的兩個(gè)分支的基礎(chǔ)上產(chǎn)生了2*2 = 4個(gè)分支

? ? ? ? ? ? ? ? 分支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賦值的時(shí)候,會(huì)產(chǎn)生總共4*2 = 8個(gè)分支,這時(shí)候遞歸枚舉也結(jié)束了,我們也得到了八個(gè)枚舉的結(jié)果?

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

? ? ? ? 實(shí)現(xiàn)代碼:

def __Count(self, i):'''結(jié)束條件:若最后一個(gè)元素也完成了枚舉,則 打印 + 運(yùn)算 '''if i == len(self.Lis):S = ''for l in self.Lis:S = S + str(self.Dic[l]) + ' 'print(S,self.__Sum(self.Str))#調(diào)用self__Sum()函數(shù)進(jìn)行運(yùn)算return'''不是結(jié)尾,則賦值并調(diào)用自己,產(chǎn)生兩個(gè)分支'''self.Dic[self.Lis[i]] = 0self.__Count(i+1)self.Dic[self.Lis[i]] = 1self.__Count(i+1)

? ? 二,再來處理計(jì)算 __Sum(self, Str)

? ? 計(jì)算的思路很簡單,我們分別設(shè)置三個(gè)值:

? ? ? ? s :用來存儲(chǔ)當(dāng)前的終值,初始值設(shè)置為-1

? ? ? ? s0 :用來存儲(chǔ)當(dāng)前式子或元素的值

? ? ? ? operater :用來存儲(chǔ)目前的操作符?

? ? 然后一個(gè)字符一個(gè)字符地循環(huán)遍歷表達(dá)式:

? ? ? ?例:str = 'A | (A & B) & C'? ?調(diào)用 __sum(self, str):

? ? ? ? 循環(huán)1:字符 = 'A",則s = A的值

? ? ? ? 循環(huán)2:字符 = '|',則operater = '|'

? ? ? ? 循環(huán)3:字符 = '(',則s0 = __sum(self, ’括號(hào)內(nèi)的那坨表達(dá)式‘),(這樣便可利用遞歸簡單地完成括號(hào)的處理)

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

? ? ? ? .......

? ? ? ? 到最后一個(gè)字符結(jié)束后,式子的值已經(jīng)存儲(chǔ)于s中了。

? ? ? ? 實(shí)現(xiàn)代碼:

#求公式結(jié)果 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]) #右邊是左括號(hào)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]#其它運(yùn)算符elif c in set("&|>=#"):operat = c#左括號(hào)elif c == '(':end = self.__Pei(i, Str)s0 = self.__Sum(Str[i+1:end])i = end#運(yùn)算結(jié)果if s == -1:s = s0s0 = -1elif operat != 0 and s0 != -1:s1 = ss = self.__Add(operat, s, s0)operat = 0s0 = -1i = i + 1return s #配對(duì)左右括號(hào) def __Pei(self, cur, Str):kflag = 1 # 左括號(hào)的數(shù)目while not kflag == 0:cur = cur + 1if Str[cur] == '(':kflag = kflag + 1elif Str[cur] == ')':kflag = kflag - 1return cur #運(yùn)算操作 def __Add(self, operator, a, b = -1):#b默認(rèn)為-1時(shí),表示是單操作符號(hào)' ! '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 -*- ''' 否.......... ! 合取........ & 可兼或...... | 不可兼或.... # 由...可得... > 當(dāng)且僅當(dāng).... = ''' class FindTruth:def __init__(self):#存儲(chǔ)字母及其真值self.Dic = {}self.Lis = []#輸入表達(dá)式self.__In()#輸出真值表self.__Out()#輸入def __In(self):#得到表達(dá)式Strself.Str = input("input your expression: \n")#篩出字母集合self.Set = set(self.Str).difference(set("()!&|>=#"))#求公式結(jié)果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]) #右邊是左括號(hào)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]#其它運(yùn)算符elif c in set("&|>=#"):operat = c#左括號(hào)elif c == '(':end = self.__Pei(i, Str)s0 = self.__Sum(Str[i+1:end])i = end#運(yùn)算結(jié)果if s == -1:s = s0s0 = -1elif operat != 0 and s0 != -1:s1 = ss = self.__Add(operat, s, s0)operat = 0s0 = -1i = i + 1return s#配對(duì)左右括號(hào)def __Pei(self, cur, Str):kflag = 1 # 左括號(hào)的數(shù)目while not kflag == 0:cur = cur + 1if Str[cur] == '(':kflag = kflag + 1elif Str[cur] == ')':kflag = kflag - 1return cur #運(yùn)算操作def __Add(self, operator, a, b = -1):#b默認(rèn)為-1時(shí),表示是單操作符號(hào)' ! '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)#構(gòu)造2^n的序列def __Count(self, i):#是結(jié)尾,打印 + 運(yùn)算if i == len(self.Lis):S = ''for l in self.Lis:S = S + str(self.Dic[l]) + ' 'print(S,self.__Sum(self.Str))return#不是結(jié)尾,遞歸賦值self.Dic[self.Lis[i]] = 0self.__Count(i+1)self.Dic[self.Lis[i]] = 1self.__Count(i+1)if __name__ == '__main__':F = FindTruth()

?

總結(jié)

以上是生活随笔為你收集整理的python - 根据表达式打印真值表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。