用python实现主范式

1.为了方便计算,可以将中缀表达式转变为后缀表达式(逆波兰式)

方法:

(1)创建一个空栈opstack,用于存放运算符,创建一个空列表output用于保存输出结果

(2)使用python字符串的split函数将输入的中缀表达式(infix)字符串分割成列表并存入input列表中。

(3)从左到右遍历input列表的每个元素token

  • 若token是运算数,直接append到output中;
  • 若token是运算符,先判断它与opstack栈顶元素的运算优先级(注:小括号的优先级约定为最低),若:token的优先级小于等于栈顶元素优先级,则先从opstack中pop出栈顶元素并append到output,再将token push进opstack;否则直接将token push 进opstack
  • 若token是左括号,一次pop出opstack中的元素并依次append到output,直到遇到左括号,将左括号继续pop出(但不append到output)

(4)当遍历完成input,将opstack中所有的剩余元素pop出并依次append到output

(5)将output转换为字符串,即为最终求得的后缀表达式

例如:

将(A+B)*C这样一个中缀表达式转换为后缀表达式(其中A,B,C)表示整数,按照上述算法,转换过程如下:

No.opstackoutput
1(
2(A
3(+A
4(+A B
5A B +
6*A B +
7*A B + C
8A B + C *

此部分代码实现:

operators = ['!','&','|','*','+']#按照优先级从高到低的顺序
#pop 函数删除栈顶的元素,top 函数查看栈顶元素。
#找到命题包含的变元
#中缀表达式转后缀表达式
def postfix(elements):  #postfix “后缀的意思”
    global operators
    stack = list()#用于存放运算符
    output = list()#用于保存输出结果

    for ele in elements:
        # ele是运算数,直接append到output
        if ele not in operators and ele not in ('(',')'):
            output.append(ele)

        #若ele是左括号,直接将其push进stack
        elif ele == '(':#小括号的优先级定为最低
            stack.append(ele)

        # 若ele是运算符,先判断它与stack栈顶元素的运算优先级。若:ele的优先级小于等于栈顶元素的优先级,
        # 则先从stack中pop出栈顶元素并append到output,再将ele push进stack;
        # 否则直接将ele push进stack
        elif ele in ('!', '&', '|', '*', '+'):
            if len(stack) == 0:
                stack.append(ele)
                continue
            while (ele == '!' and stack[-1] == '!') or \
                    (ele == '&' and stack[-1] in ('!', '&')) or \
                    (ele == '|' and stack[-1] in ('!', '&', '|')) or \
                    (ele == '*' and stack[-1] in ('!', '&', '|', '*')) or \
                    (ele == '+' and stack[-1] in ('!', '&', '|', '*', '+')):
                val = stack.pop()
                output.append(val)
                if not stack:
                    break
            stack.append(ele)

        #若ele是右括号,依次pop出stack中的元素并依次append到output,
        #直到遇到左括号,将左括号继续pop出(但不append到output)
        elif ele == ')':
            val = stack.pop()
            while val != '(':
                output.append(val)
            # if stack:
            # # 如果stack列表还有元素执行这块
            # else:
            # # 如果stack列表没有元素了执行这块
                if stack:
                    val = stack.pop()
                else:
                    break

    #当表达式完全处理完之后,把栈中的运算符一一出栈,转化成后缀表达式
    while stack != []:
        output.append(stack.pop())
    return ''.join(output)
#print('请输入运算式:')
#inp = input('')
#expr = postfix(inp)
#print(expr)

2.打印真值表(前面一部分):

此处打印真值表采用的是bin()函数。通过对此函数的使用,可以较为简洁的列出所有变元的所有情况。(这时还不包括最后的值,仅仅只是变元的所有情况)

代码如下:

var = list()
#找出变元且不能重复
for item in expr:
    if item not in operators and \
            item not in var and \
            item not in ('(',')'):
        var.append(item)

lt = []
vlen = len(var)
n = 2 ** vlen
for i in range(0, n):
    tlt = list(bin(i))
    tlt.pop(0)
    tlt.pop(0)
    tlen = len(tlt)
    for j in range(0, vlen - tlen):
        tlt.insert(0, '0')
    print(tlt)
    lt.append(tlt)
# print(lt)

除此之外,打印真值表还可以采用枚举法,也就是对变元(需要将所有变元找出来)的T、F的枚举。相当于未知阶的嵌套循环,对此应该用递归解决。

3.再考虑命题的计算,分别写出几种运算(非、析取、合取、单条件、双条件)的计算方式

代码实现如下:

def logica10p(tmp):
    idx = 0  #当前命题元素的位置
    while len(tmp)>1:  #当最后命题仅为真值后,退出循环
        if tmp[idx] in operators:
            if tmp[idx] == '!':  #非运算
                #这里把命题变元进行转换,根据后缀表达式,一定满足idx的前一位或前2位是真值而不是运算符
                tmp[idx - 1] = 1 if int(tmp[idx - 1]) == 0 else 0
                tmp[idx:idx + 1] = []  #子命题结果对原命题的覆盖
                #每次从头开始对命题处理
                idx = 0
                continue
            elif tmp[idx] == '&':  #合取运算
                tmp[idx] = 1 if int(tmp[idx - 1]) == 1 and int(tmp[idx - 2]) == 1 else 0
                tmp[idx - 2:idx] = []
                idx = 0
                continue
            elif tmp[idx] == '|':  #析取运算
                tmp[idx] = 0 if int(tmp[idx - 1]) == 0 and int(tmp[idx - 2]) == 0 else 1
                tmp[idx - 2:idx] = []
                idx = 0
                continue
            elif tmp[idx] == '*':  #单条件
                tmp[idx] = 0 if int(tmp[idx - 2]) == 1 and int(tmp[idx - 1]) == 0 else 1
                tmp[idx - 2:idx] = []
                idx = 0
                continue
            elif tmp[idx] == '+':  #双条件
                tmp[idx] = 1 if int(tmp[idx - 2]) == int(tmp[idx - 1]) else 0
                tmp[idx - 2:idx] = []
                idx = 0
                continue
        idx += 1
    # print(tmp[0])
    return tmp[0]

4.使用上述函数logical0p()打印命题各种情况的结果

代码如下:

result = []
for i in lt:
    tmp1 = str(expr)
    for j in range(0, vlen):
        # print(tmp,var[j],i[j])
        tmp1 = tmp1.replace(var[j], i[j])  # 将每个变量的位置用对应的真值组合中的0或1代替
    # print(tmp1)
    tmp = list(tmp1)
    # print(tmp)
    a = logica10p(tmp)
    result.append(a)
print(result)

5.最后,由于上述的结果均为一个列表,需要在将其转换一下:

# 开始输出真值表
k = 0
print("\n真值表>>>")
# print('\t'.join(var),end='\t') #结果为  p	q	r	s
for i in var:
    print(i, "\t", end='')
print(inp, "")
for i in lt:
    for j in range(0, vlen):
        print(i[j], "\t", end='')
    print(result[k])
    k = k + 1
idx = 0
for nl in range(0,n):
    if result[idx] == 1:
        ornl.append(nl)
    else:
        andnl.append(nl)
    idx += 1

print('主析取范式:')
print('∑', ornl)
print('主合取范式:')
print('∏', andnl)

完整代码:

# !:非(单命题变元)
# &:合取
# |:析取
# *:单条件(则)
# +:双条件(当且仅当)
operators = ['!','&','|','*','+']#按照优先级从高到低的顺序
#pop 函数删除栈顶的元素,top 函数查看栈顶元素。
#找到命题包含的变元
#中缀表达式转后缀表达式
def postfix(elements):  #postfix “后缀的意思”
    global operators
    stack = list()#用于存放运算符
    output = list()#用于保存输出结果

    for ele in elements:
        # ele是运算数,直接append到output
        if ele not in operators and ele not in ('(',')'):
            output.append(ele)

        #若ele是左括号,直接将其push进stack
        elif ele == '(':#小括号的优先级定为最低
            stack.append(ele)

        # 若ele是运算符,先判断它与stack栈顶元素的运算优先级。若:ele的优先级小于等于栈顶元素的优先级,
        # 则先从stack中pop出栈顶元素并append到output,再将ele push进stack;
        # 否则直接将ele push进stack
        elif ele in ('!', '&', '|', '*', '+'):
            if len(stack) == 0:
                stack.append(ele)
                continue
            while (ele == '!' and stack[-1] == '!') or \
                    (ele == '&' and stack[-1] in ('!', '&')) or \
                    (ele == '|' and stack[-1] in ('!', '&', '|')) or \
                    (ele == '*' and stack[-1] in ('!', '&', '|', '*')) or \
                    (ele == '+' and stack[-1] in ('!', '&', '|', '*', '+')):
                val = stack.pop()
                output.append(val)
                if not stack:
                    break
            stack.append(ele)

        #若ele是右括号,依次pop出stack中的元素并依次append到output,
        #直到遇到左括号,将左括号继续pop出(但不append到output)
        elif ele == ')':
            val = stack.pop()
            while val != '(':
                output.append(val)
            # if stack:
            # # 如果stack列表还有元素执行这块
            # else:
            # # 如果stack列表没有元素了执行这块
                if stack:
                    val = stack.pop()
                else:
                    break

    #当表达式完全处理完之后,把栈中的运算符一一出栈,转化成后缀表达式
    while stack != []:
        output.append(stack.pop())
    return ''.join(output)

def logica10p(tmp):
    idx = 0  #当前命题元素的位置
    while len(tmp)>1:  #当最后命题仅为真值后,退出循环
        if tmp[idx] in operators:
            if tmp[idx] == '!':  #非运算
                #这里把命题变元进行转换,根据后缀表达式,一定满足idx的前一位或前2位是真值而不是运算符
                tmp[idx - 1] = 1 if int(tmp[idx - 1]) == 0 else 0
                tmp[idx:idx + 1] = []  #子命题结果对原命题的覆盖
                #每次从头开始对命题处理
                idx = 0
                continue
            elif tmp[idx] == '&':  #合取运算
                tmp[idx] = 1 if int(tmp[idx - 1]) == 1 and int(tmp[idx - 2]) == 1 else 0
                tmp[idx - 2:idx] = []
                idx = 0
                continue
            elif tmp[idx] == '|':  #析取运算
                tmp[idx] = 0 if int(tmp[idx - 1]) == 0 and int(tmp[idx - 2]) == 0 else 1
                tmp[idx - 2:idx] = []
                idx = 0
                continue
            elif tmp[idx] == '*':  #单条件
                tmp[idx] = 0 if int(tmp[idx - 2]) == 1 and int(tmp[idx - 1]) == 0 else 1
                tmp[idx - 2:idx] = []
                idx = 0
                continue
            elif tmp[idx] == '+':  #双条件
                tmp[idx] = 1 if int(tmp[idx - 2]) == int(tmp[idx - 1]) else 0
                tmp[idx - 2:idx] = []
                idx = 0
                continue
        idx += 1
    # print(tmp[0])
    return tmp[0]
print('请输入运算式:')
inp = input('')  #例如:p&q|r*q&!s|r
expr = postfix(inp)  #pq&r|qs!&r|*
ornl = []
andnl = []
var = list()
#找出变元且不能重复
for item in expr:
    if item not in operators and \
            item not in var and \
            item not in ('(',')'):
        var.append(item)

lt = []
vlen = len(var)
n = 2 ** vlen
for i in range(0, n):
    tlt = list(bin(i))
    tlt.pop(0)
    tlt.pop(0)
    tlen = len(tlt)
    for j in range(0, vlen - tlen):
        tlt.insert(0, '0')
    print(tlt)
    lt.append(tlt)
# print(lt)

result = []
for i in lt:
    tmp1 = str(expr)
    for j in range(0, vlen):
        # print(tmp,var[j],i[j])
        tmp1 = tmp1.replace(var[j], i[j])  # 将每个变量的位置用对应的真值组合中的0或1代替
    # print(tmp1)
    tmp = list(tmp1)
    # print(tmp)
    a = logica10p(tmp)
    result.append(a)
print(result)

# 开始输出真值表
k = 0
print("\n真值表>>>")
# print('\t'.join(var),end='\t') #结果为  p	q	r	s
for i in var:
    print(i, "\t", end='')
print(inp, "")
for i in lt:
    for j in range(0, vlen):
        print(i[j], "\t", end='')
    print(result[k])
    k = k + 1
idx = 0
for nl in range(0,n):
    if result[idx] == 1:
        ornl.append(nl)
    else:
        andnl.append(nl)
    idx += 1

print('主析取范式:')
print('∑', ornl)
print('主合取范式:')
print('∏', andnl)

参考:https://mbd.baidu.com/ma/s/LJcQ0Efm

           https://www.cnblogs.com/cxy229/p/4829232.html

           https://blog.csdn.net/dnxbjyj/article/details/71248637

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值