精华内容
下载资源
问答
  • 南京邮电大学实验一真值表法求主析取范式主合取范式代码 离散数学 实 验 一利用真值表法求取主析取范式以及主合取范式的实现 实验名称:利用真值表法求取主析取范式以及主合取范式的实现 实验目的:通过编程实现...
  • 编程实现求解逻辑表达式的真值表、主析取范式主合取范式对于一个含n个命题变元的表达式(n为相异的命题变元总个数),其真值表可看作由从0到2ⁿ-1的二进制数的变化表。因此,可以通过按行列举0到2ⁿ-1的二进制数来...
  • C语言实现主析取范式 第一次写,不喜勿喷 (先来水一波) 先保证输入的式子是合法的 (不合法我也不会,太弱了) 难点主要是计算真值表,可以用堆栈实现,建立两个堆栈,一个储存操作符,另一个储存数值 (手写堆栈) ...

    C语言实现主析取范式

    第一次写,不喜勿喷
    (先来水一波)
    先保证输入的式子是合法的 (不合法我也不会,太弱了)
    难点主要是计算真值表,可以用堆栈实现,建立两个堆栈,一个储存操作符,另一个储存数值 (手写堆栈)

    int OPNUM[300], OPOP[300], inum = 0, inop = 0;//储存数字和操作符的堆
    

    储存的是int类型,在这之前有将操作符转化成对应的优先级

    int charge_operator(char ch){//判断优先级
        if (ch == '!') return 1;
        else if (ch == '&') return 2;
        else if (ch == '|') return 3;
        else if (ch == '$') return 4;//单条件
        else if (ch == '@') return 5;//双条件
        else if (ch == '(') return 6;
        else if (ch == ')') return 7;
        return 10;
    }
    

    如果上一个操作符和这个操作符的优先级相同或者上一个操作符的优先级大于这个操作的优先级,则可以计算,也就是取上一个操作的操作符,和数值栈的前两个元素计算,然后再压入栈。否则操作符直接入栈,操作符堆其实是维持一个单调递增的序列。

    if(cha>=OPOP[inop] && inop){//保证有操作符
    	   int op = OPOP[inop];
    	   int a, b, c;
    	   a = OPNUM[inum-1], b = OPNUM[inum], inum--;//取数值栈的前两个
    	   c = operator_A(op, a, b);//计算数值
    	   OPNUM[inum]=c;//数值入栈
    	   OPOP[inop] = cha;//操作符入栈
    }
    else OPOP[++inop]=cha;
    

    这里主要判断一下条件非,和左括号:
    条件非的判断:只需要在每个数值入栈之前看一下操作符是不是条件非

    //f数组用来储存表达式
    if (f[i]=='0' || f[i] == '1'){
                if (OPOP[inop] == 1) {OPNUM[++inum] = (f[i] == '1'? 0:1); inop--;} //判断!的情况
                else OPNUM[++inum] = f[i] - '0';
            }
    

    在条件非入栈的时候,看一下上一个操作符是不是条件非,如果是两个条件非就相互抵消了,例如!!0, 两个非就直接抵消。

    如果是左括号直接入栈,如果是右括号,直接往前计算到左括号。
    最后别忘记堆栈中剩余的元素

     while(inop!=0){
            int op = OPOP[inop];
            inop--;
            int a, b, c;
            a = OPNUM[inum-1], b = OPNUM[inum], inum--;
            c = operator_A(op, a, b);
            OPNUM[inum]=c;
        }
    

    直接上代码

    #include<stdio.h>
    #include<bits/stdc++.h>
    #define extraction '|' //析取
    #define conjunction '&' //合取
    #define non '!'//非
    /*
    双条件@
    单条件$
    */
    char forluma[1100]; //表示表达式和表达式的列数,数组从1开始
    int n, col, row,num;//用来储存真值表中的行数和列数,num表示变量的个数
    int Map[300][300],mp[300],nowval[30];//用mp维护数组,map存放真值表,nowval存当前表达式每个字母的取值
    void init(){
        memset(forluma,0, sizeof(forluma));
        memset(Map, 0, sizeof(Map));
        memset(mp, 0, sizeof(mp));
        col=0,row=0;
    }
    void read(){
        char ch;
        int cnt = 0;
        while(scanf("%c", &ch) != EOF){
            if ((ch >='A' && ch <= 'Z') || ch == '(' || ch == ')' || ch ==extraction || ch == conjunction || ch == non
            || ch == '@' || ch == '$'){//去掉输入的空格空格
                forluma[++cnt] = ch;
            }
            if (ch >='A'&&ch<='Z'&&!mp[ch]){//用mp维护字母
                mp[ch]=++num;
            }
        }
        n = cnt, cnt = 0;
        for (int i = 1; i <= 100; i++){//离散化变量
            if (mp[i])mp[i]=++cnt;
        }
    }
    int operator_A(int ch, int x, int y){//计算式子的值
        if (ch == 2) return x & y;
        else if (ch == 3) return x | y;
        else if (ch == 4){
            if (x == 1 && y == 0) return 0;
            else return 1;
        } 
        else if(ch == 5){
            if (x == y) return 1;
            else return 0;
        }
        return 0;
    }
    int charge_operator(char ch){//判断优先级
        if (ch == '!') return 1;
        else if (ch == '&') return 2;
        else if (ch == '|') return 3;
        else if (ch == '$') return 4;
        else if (ch == '@') return 5;
        else if (ch == '(') return 6;
        else if (ch == ')') return 7;
        return 10;
    }
    
    char f[1200];//赋值的式子
    int calculate(){
        for (int i = 1; i <= n; i++){//把每个字母的值赋值给式子
            if (forluma[i] >='A' && forluma[i] <= 'Z') f[i]=nowval[mp[forluma[i]]] + '0';
            else f[i] = forluma[i];
        }
        int OPNUM[300], OPOP[300], inum = 0, inop = 0;//储存数字和操作符的堆
        for (int i = 1; i <= n; i++){
            if (f[i]=='0' || f[i] == '1'){
                if (OPOP[inop] == 1) {OPNUM[++inum] = (f[i] == '1'? 0:1); inop--;} //判断!的情况
                else OPNUM[++inum] = f[i] - '0';
            }
            else {
                int cha = charge_operator(f[i]);
                if(cha == 7){//右括号的情况
                    int op = OPOP[inop]; inop--;//取运算符
                    while(op != 6){//一直算到左括号
                        int a, b, c;
                        a = OPNUM[inum-1], b = OPNUM[inum], inum--;
                        c = operator_A(op, a, b);
                        OPNUM[inum]=c;
                        op=OPOP[inop--];
                    }
                    op=OPOP[inop];
                    if(op==1) {OPNUM[inum] = !OPNUM[inum];inop--;}//判断'('前面是不是条件非
                }
                else if(cha == 6) OPOP[++inop] = cha;
                else if (cha == 1){//条件非的判断
                    if(OPOP[inop] == 1) inop--;//!!0 = 0,两个非相互抵消
                    else OPOP[++inop] = cha;
                }
                else{
                    if(cha>=OPOP[inop] && inop){//保证有操作符,上一个操作符的优先级大于等于这个操作的优先级
                        int op = OPOP[inop];
                        int a, b, c;
                        a = OPNUM[inum-1], b = OPNUM[inum], inum--;
                        c = operator_A(op, a, b);
                        OPNUM[inum]=c;
                        OPOP[inop] = cha;
                    }
                    else OPOP[++inop]=cha;
                }
            }
        }
        while(inop!=0){//最后清空操作符栈
            int op = OPOP[inop];
            inop--;
            int a, b, c;
            a = OPNUM[inum-1], b = OPNUM[inum], inum--;
            c = operator_A(op, a, b);
            OPNUM[inum]=c;
        }
        return OPNUM[1];
    }
    void dfs(int now_x){//枚举每一种情况
        if (now_x  == num){
            row++;
            for (int i = 1; i <= now_x; i++) Map[row][i] = nowval[i];
            Map[row][now_x+1] = calculate();
            return ;
        }
        nowval[now_x + 1] = 0;
        dfs(now_x + 1);
        nowval[now_x + 1] = 1;
        dfs(now_x + 1);
    }
    
    void work(){
        dfs(0);
        printf("真值表:\n\t\t");
        char abc[30];
        int cnt = 0;
        for (int i = 1; i <= 100; i++){
            if (mp[i]) {printf("%c ", i);abc[++cnt]=i;}
        }
        printf("\n\t\t");
        for(int i = 1; i<=row; i++){
            for (int j = 1; j <= num + 1; j++){
                printf("%d ",Map[i][j]);
            }
            printf("\n\t\t");
        }
        char xi[2000], he[2000];
        int x=0, h=0;
        for (int i = 1; i <= row; i++){
            if (Map[i][num+1]==1){
                if (x) xi[++x] = '|';
                xi[++x] = '(';
                for (int j = 1; j <= num; j++){
                    if(j!=1)xi[++x]='&';
                    if (Map[i][j] == 0)xi[++x]='!';
                    xi[++x]=abc[j];
                }
                xi[++x]=')';
            }
            else {
                if (h)he[++h]='&';
                he[++h]='(';
                for (int j = 1; j <= num; j++){
                    if (j!=1)he[++h]='|';
                    if (Map[i][j]==1)he[++h]='!';
                    he[++h]=abc[j];
                }
                he[++h]=')';
            }
        }
        printf("\n主析取范式:");
        for (int i = 1; i <= x; i++) {
            if (xi[i]=='|') printf("∨");
            else if (xi[i]=='&') printf("∧");
            else if (xi[i]=='!') printf("ㄱ");
            else printf("%c",xi[i]);
        }
        printf("\n主合取范式:");
        for (int i = 1; i <= h; i++){
            if (he[i]=='|') printf("∨");
            else if (he[i]=='&') printf("∧");
            else if (he[i]=='!') printf("ㄱ");
            else printf("%c",he[i]);
        }
    }
    
    int main(){
        printf("请输入逻辑表达式:\n");
        printf("与逻辑:&  或逻辑:|  非逻辑:! 单条件:$  双条件:@\n");
        printf("请注意:表达式错误程序可能无法运行或者结果错误\n");
        init();
        read();
        work();
    }
    

    输入:

    (P$R)&(Q$!R)&(!R$(P|Q))
    

    输出:

    请输入逻辑表达式:
    与逻辑:&  或逻辑:|  非逻辑:! 单条件:$  双条件:@
    请注意:表达式错误程序可能无法运行或者结果错误
    真值表:
    		P Q R 
    		0 0 0 0 
    		0 0 1 1 
    		0 1 0 1 
    		0 1 1 0 
    		1 0 0 0 
    		1 0 1 1 
    		1 1 0 0 
    		1 1 1 0 
    		
    主析取范式:(P∧ㄱQR)(PQ∧ㄱR)(P∧ㄱQR)
    主合取范式:(PQR)(P∨ㄱQ∨ㄱR)(PQR)(P∨ㄱQR)(P∨ㄱQ∨ㄱR)
    

    如有错误欢迎指正

    展开全文
  • 研究生人工智能课的作业,主合取范式转主析取范式,敲了四五个小时,亲测可用,python版本的,用anaconda可直接运行,注释详细,要的自取
  • 离散数学实验报告
  • 实 验 一利用真值表法求取主析取范式以及主合取范式的实现 实验名称:利用真值表法求取主析取范式以及主合取范式的实现 实验目的:通过编程实现主析取范式以及主合取范式的真值表求法以巩固相关理论的掌握 实验...
  • 主析取范式主合取范式的c++求解程序

    千次阅读 多人点赞 2019-10-27 19:40:14
    主要思想是:先求真值表,再根据真值表输出主析取范式主合取范式。 用!来表示非,用小写v表示析取,用^来表示合取,用~来表示双条件,用-来表示条件,用大写字母来表示命题变元。 真值表的求...

    这是我们老师刚刚布置的作业,自己百度了一下,发现没有比较简单完善的程序代码,于是自己写成功后,与大家分享一下。有些地方描述的不好,可能比较难理解,请见谅。如果有啥不懂的,可以在下面评论,我会尽力解答
    一、算法思想
    主要思想是:先求真值表,再根据真值表输出主析取范式和主合取范式。

    用!来表示非,用小写v表示析取,用^来表示合取,用~来表示双条件,用-来表示条件,用大写字母来表示命题变元。

    真值表的求解
    ① 根据命题的个数n,得出所有命题变元赋值的情况个数sum,例如n=4个命题变元,则有sum=2^4种情况,并将所有情况存入二维数组a[i][j]中,a[i]代表第i种情况。
    ② 创建两个栈,一个用来存放操作符Operator,先自己在栈里面存放字符‘#’(输入命题公式时要最后应该加一个字符‘#’);一个存放操作数Operand。
    ③ 根据表达式求值的思想,读取表达式,若是操作符,则与之前的操作符相比优先级,若大于前者,则读取下一个;若相等,则说明两者为()则弹出前者,读取下一个;若小于前者,则可以进行运算;
    ④ 若读取的是操作数,则在数组a中读取操作数所对应的数,存入栈中;
    ⑤ 将最后的运算结果存入数组result中,再次循环步骤③,循环sum次即可
    ⑥ 根据result的结果,当输出主析取范式时,当result[i]==1时,则输出相应的命题变元(当命题变元为1则输出P,为0则输出!P),把result都遍历一遍,将结果为1的都连在一起即可;求取主合取范式就将result=0的输出连在一起即可;
    二、源代码

    第一个头文件const.h//预定义常量头文件
    #pragma once

    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 1
    #define INFEASIBLE -1
    #define OVERFLOW -2

    typedef int Status;

    第二个头文件prefunction.h//变量类型的定义与函数的声明
    #pragma once

    #include"const.h"

    #define STACK_INIT_SIZE 100
    #define STACKINCREMENT 10

    typedef char SElemType;

    typedef int SElemType_1;

    typedef struct {
    SElemType *base;
    SElemType *top;
    int stacksize;
    }SqStack;//操作符栈

    typedef struct {
    SElemType_1 *INTbase;
    SElemType_1 *INTtop;
    int INTstacksize;
    }INTStack;//操作数栈
    Status InitStack(SqStack &S);//初始化
    Status GetTop(SqStack S, SElemType &e);//读栈顶
    Status Push(SqStack &S, SElemType e);//入栈
    Status Pop(SqStack &S, SElemType &e);//出栈
    Status initStack(INTStack &S);// 初始化
    Status pop(INTStack &S, SElemType_1 &e);// 出栈
    Status push(INTStack &S, SElemType_1 e);// 入栈
    char precede(SElemType e1, SElemType e2);//判断操作数的优先级
    Status bothway(int &a, SElemType b, int c);//双向运算符操作
    Status TruthTable(int a[65][6], int count,char ch[6]);//真值表
    Status Proposition(char a[50], char ch[6]);//求命题的个数

    第二个头文件function.h
    #pragma once
    #include
    #include
    #include

    #include"prefunction.h"

    Status InitStack(SqStack &s) {
    //构造一个空的栈
    s.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!s.base)
    exit(OVERFLOW);
    s.top = s.base;
    s.stacksize = STACK_INIT_SIZE;
    return OK;
    }
    Status GetTop(SqStack s, SElemType &e) {
    //获得栈顶元素
    if (s.top == s.base)
    return ERROR;
    e = (s.top - 1);
    return OK;
    }
    Status Push(SqStack &s, SElemType e) {
    //插入元素e为新的栈顶
    if (s.top - s.base >= s.stacksize) {
    s.base = (SElemType
    )realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(SElemType));
    if (!s.base)
    exit(OVERFLOW);
    s.top = s.base + s.stacksize;
    s.stacksize += STACKINCREMENT;
    }
    *s.top++ = e;
    return OK;
    }
    Status Pop(SqStack &s, SElemType &e) {
    //弹出栈顶元素
    if (s.top == s.base)
    return ERROR;
    e = –s.top;
    return OK;
    }
    Status initStack(INTStack &s)
    {
    //构造一个空的栈
    s.INTbase = (SElemType_1
    )malloc(STACK_INIT_SIZE * sizeof(SElemType_1));
    if (!s.INTbase)
    exit(OVERFLOW);
    s.INTtop = s.INTbase;
    s.INTstacksize = STACK_INIT_SIZE;
    return OK;
    }
    Status pop(INTStack &s, SElemType_1 &e)
    {//弹出栈顶元素
    if (s.INTtop == s.INTbase)
    return ERROR;
    e = –s.INTtop;
    return OK;
    }
    Status push(INTStack &s, SElemType_1 e)
    {
    //插入元素e为新的栈顶
    if (s.INTtop - s.INTbase >= s.INTstacksize) {
    s.INTbase = (SElemType_1
    )realloc(s.INTbase, (s.INTstacksize + STACKINCREMENT) * sizeof(SElemType_1));
    if (!s.INTbase)
    exit(OVERFLOW);
    s.INTtop = s.INTbase + s.INTstacksize;
    s.INTstacksize += STACKINCREMENT;
    }
    *s.INTtop++ = e;
    return OK;
    }
    char precede(SElemType e1, SElemType e2)//判断操作数的优先级
    {
    if (e1 == ‘v’&&e2 == ‘v’)
    return ‘>’ ;
    if (e1 == ‘v’&&e2 == ‘^’)
    return ‘>’;
    if (e1 == ‘v’&&e2 == ‘~’)
    return ‘>’;
    if (e1 == ‘v’&&e2 == ‘-’)
    return ‘>’;
    if (e1 == ‘v’&&e2 == ‘)’)
    return ‘>’;
    if (e1 == ‘v’&&e2 == ‘(’)
    return ‘<’;
    if (e1 == ‘v’&&e2 == ‘#’)
    return ‘>’;

    if (e1 == '^'&&e2 == 'v')
    	return '>';
    if (e1 == '^'&&e2 == '^')
    	return '>';
    if (e1 == '^'&&e2 == '~')
    	return '>';
    if (e1 == '^'&&e2 == '-')
    	return '>';
    if (e1 == '^'&&e2 == ')')
    	return '>';
    if (e1 == '^'&&e2 == '(')
    	return '<';
    if (e1 == '^'&&e2 == '#')
    	return '>';
    
    if (e1 == '-'&&e2 == 'v')
    	return '>';
    if (e1 == '-'&&e2 == '^')
    	return '>';
    if (e1 == '-'&&e2 == '~')
    	return '>';
    if (e1 == '-'&&e2 == '-')
    	return '>';
    if (e1 == '-'&&e2 == ')')
    	return '>';
    if (e1 == '-'&&e2 == '(')
    	return '<';
    if (e1 == '-'&&e2 == '#')
    	return '>';
    
    if (e1 == '~'&&e2 == 'v')
    	return '>';
    if (e1 == '~'&&e2 == '^')
    	return '>';
    if (e1 == '~'&&e2 == '~')
    	return '>';
    if (e1 == '~'&&e2 == '-')
    	return '>';
    if (e1 == '~'&&e2 == ')')
    	return '>';
    if (e1 == '~'&&e2 == '(')
    	return '<';
    if (e1 == '~'&&e2 == '#')
    	return '>';
    
    if (e1 == '('&&e2 == 'v')
    	return '<';
    if (e1 == '('&&e2 == '^')
    	return '<';
    if (e1 == '('&&e2 == '~')
    	return '<';
    if (e1 == '('&&e2 == '-')
    	return '<';
    
    
    
    if (e1 == '#'&&e2 == 'v')
    	return '<';
    if (e1 == '#'&&e2 == '^')
    	return '<';
    if (e1 == '#'&&e2 == '~')
    	return '<';
    if (e1 == '#'&&e2 == '-')
    	return '<';
    if (e1 == '#'&&e2 == '(')
    	return '<';
    
    if (e1 == '!'&&e2 == 'v')
    	return '>';
    if (e1 == '!'&&e2 == '^')
    	return '>';
    if (e1 == '!'&&e2 == '~')
    	return '>';
    if (e1 == '!'&&e2 == '-')
    	return '>';
    if (e1 == '!'&&e2 == ')')
    	return '>';
    if (e1 == '!'&&e2 == '(')
    	return '<';
    if (e1 == '!'&&e2 == '#')
    	return '>';
    
    
    
    if (e1 == 'v'&&e2 == '!')
    	return '<';
    if (e1 == '^'&&e2 == '!')
    	return '<';
    if (e1 == '~'&&e2 == '!')
    	return '<';
    if (e1 == '-'&&e2 == '!')
    	return '<';
    if (e1 == '#'&&e2 == '!')
    	return '<';
    
    
    
    
    
    if (e1 == '('&&e2 == '(')
    	return '<';
    if (e1 == '('&&e2 == ')')
    	return '=';
    return 'p';
    

    }
    //用小写的v来表示析取;用^来表示合取;用-来表示条件;用~来表示双条件;
    Status bothway(int &a, SElemType b, int c)
    {
    if ( b ==‘v’) {
    if (a == 0 && c == 0)
    a = 0;
    else
    a = 1;
    }
    if (b ‘^’) {
    if (a == 1 && c == 1)
    a = 1;
    else
    a = 0;
    }
    if (b == ‘-’) {
    if (a == 1 && c == 0)
    a = 0;
    else
    a = 1;
    }
    if (b == ‘~’) {
    if (a == c)
    a = 1;
    else
    a = 0;
    }
    return OK;
    }
    Status TruthTable(int a[65][6], int count,char ch[6])//真值表
    {
    int i,sum=1,s,k,j;
    for (i = 0; i < count; i++)
    sum = sum * 2;
    i = 1;
    s = sum;
    while (i <= count) {
    s = s / 2;
    k = 0;
    j = 1;
    while (j <= sum) {
    if((j/s)%2
    0)
    for (k = 0; k < s; k++) {
    a[j-1][i-1] = 0; j++;
    }
    else
    for (k = 0; k < s; k++) {
    a[j-1][i-1] = 1; j++;
    }
    }
    i++;
    }

    return OK;
    

    }
    Status Proposition(char a[50], char ch[6])//求命题的个数
    {
    int i=0,j=0,k=0;
    int flag = 0;
    while (a[i]) {
    if (a[i] >= 65 && a[i] <= 90) {
    while (ch[j]) {
    if (a[i] == ch[j])
    flag = 1;
    j++;
    }
    if (flag == 0) {
    ch[k] = a[i];
    k++;
    }
    flag = 0;
    j = 0;
    }
    i++;
    }
    return OK;
    }
    第四个文件是cpp文件:xiquhequ.cpp
    #include"function.h"

    using namespace std;

    int main() {

    int n,a[65][6],sum=1,s;
    char exqu[50], ch[6] = {0};
    printf_s("请输入命题的个数:");
    scanf("%d", &n);
    printf_s("请输入命题表达式:");
    scanf("%s", exqu);
    for (s = 0; s < n; s++) {
    	sum = sum * 2;
    }//求所有的情况个数sum
    
    
    Proposition(exqu,ch);//将n个变量变元提取出来存入字符数组ch
    
    TruthTable(a, n, ch);//将所有情况存入数组a中
    
    
    SqStack Operator;//操作符栈
    INTStack Operand;//操作数栈
    InitStack(Operator);//初始化
    initStack(Operand);//初始化
    
    
    SElemType e;
    int k = 0,result[65];
    int i = 0,j=0;
    SElemType_1 p, q;
    SElemType	E;
    
    while (k < sum)
    {
    	*Operator.top = '#';
    	Operator.top++;
    	GetTop(Operator, e);
    	i = 0;
    	while (exqu[i] != '#' || e != '#') 
    	{
    
    
    		if (exqu[i] <= 90 && exqu[i] >= 65) {
    			while (exqu[i] != ch[j]) {
    				j++;
    			}
    			push(Operand, a[k][j]);
    			//print(Operand);
    			//*Operand.INTtop = a[k][j];// printf_s("%d", a[k][j]);
    			//Operand.INTtop++;
    			j = 0;
    			i++;
    		}
    		else {
    			GetTop(Operator, e);
    			switch (precede(e, exqu[i])) {
    			case '<':Push(Operator, exqu[i]); i++;
    				break;
    			case '=':Pop(Operator, e); i++;
    				break;
    			case '>':Pop(Operator, E); 
    				if (E == '!')
    				{
    					pop(Operand, p);
    					if (p == 0)
    						p = 1;
    					else
    						p = 0;	
    					push(Operand, p);
    
    					//print(Operand);
    					//printf("%d", p);
    				}
    				else
    				{
    					pop(Operand, p); pop(Operand, q);  bothway(q, E, p); push(Operand, q);//print(Operand);
    				}
    				break;
    			default:printf_s("precede函数返回值错误\n");
    			}
    		}
    		GetTop(Operator, e);
    	}
    
    	pop(Operand, q);
    	//printf("%d\n", q);
    	result[k] = q;
    	k++;
    	Pop(Operator, e);
    	//Pop(Operator, e);
    
    
    }
    
    
    for (i = 0; i < n; i++) {
    	printf_s("%c    ", ch[i]);
    }
    i = 0;
    while (exqu[i]!='#') {
    	printf_s("%c", exqu[i]);
    	i++;
    }
    printf_s("\n");
    for (k = 0; k < sum; k++) {
    
    	for (i = 0; i < n; i++) {
    		printf_s("%d    ", a[k][i]);
    	}
    	printf_s("%d", result[k]);
    	printf_s("\n");
    }
    
    //输出主析取范式
    printf_s("主析取范式\n");
    for (k = 0; k < sum; k++)
    {
    	if (result[k] == 1)
    	{
    		printf_s("(");
    		for (i = 0; i < n; i++)
    		{
    			if (a[k][i] == 1)
    				printf_s("%c^", ch[i]);
    			else
    				printf_s("!%c^", ch[i]);
    		}
    		printf_s("\b)v");
    	}		
    }
    printf_s("\b \n");
    
    //输出主合取范式
    printf_s("主合取范式\n");
    for (k = 0; k < sum; k++)
    {
    	if (result[k] == 0)
    	{
    		printf_s("(");
    		for (i = 0; i < n; i++)
    		{
    			if (a[k][i] == 1)
    				printf_s("%c^", ch[i]);
    			else
    				printf_s("!%c^", ch[i]);
    		}
    		printf_s("\b)v");
    	}
    }
    printf_s("\b ");
    getchar();
    getchar();
    return 0;
    

    }
    三,输入输出结果

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 主析取范式主合取范式

    万次阅读 多人点赞 2019-04-08 02:27:36
    主析取范式主合取范式 定义设A为恰含命题变元p1,…,pn的公式。公式A'称为A的主析(合)取范式(majordisjunctive(conjunctive)normal form),如果A'是A的析(合)取范式,并且其每个合(析)取子句中p1,…,...

    主析取范式与主合取范式

     

    定义    设A为恰含命题变元p1,…,pn的公式。公式A'称为A主析(合)取范式(majordisjunctive(conjunctive)normal form),如果A'是A的析(合)取范式,并且其每个合(析)取子句中p1,…,pn均恰出现一次。

    据定义,例1.21中公式┐p→┐(p→q)的主析取范式是(p∧q)∨(p∧┐q),而其主合取范式则应是(p∨q)∧(p∨┐q)。

         例1  求公式(p∧q)∨r的主析取范式及主合取范式。

        (p∧q)∨r

         (p∧q∧(r∨┐r))∨((p∨┐p)∧(q∨┐q)∧r)

         (p∧q∧r)∨(p∧q∧┐r)∨(p∧q∧r)∨(p∧┐q∧r)∨(┐p∧q∧r)∨(┐p∧┐q∧r)

         (p∧q∧r)∨(p∧q∧┐r)∨(p∧┐q∧r)∨(┐p∧q∧r)∨(┐p∧┐q∧r)

        此即所求的主析取范式。另外

    (p∧q)∨r

    (p∨r)∧(q∨r)

    (p∨(q∧┐q)∨r)∧((p∧┐p)∨q∨r)

    (p∨q∨r)∧(p∨┐q∨r)∧(p∨q∨r)∧(┐p∨q∨r)

    (p∨q∨r)∧(p∨┐q∨r)∧(┐p∨q∨r)

    最后一式即为所求的主合取范式。

    **** 我们总结一下利用等价推演求公式的主析(合)取范式的方法步骤:

    第一步:求出该公式的析(合)取范式;

    第二步:简化各子句.除去范式中所有恒假(真)的合(析)取子句,即化掉含有互补文字对的合(析)取子句;将合(析)取子句中同一命题变元的多个出现合并为一个;

    第三步:对析(合)取范式中合(析)取子句不是每一变元都出现的,利用pp∧tp∧(q∨┐q)或pp∨fp∨ (q∧┐q)把未出现的变元补进来,并用分配律将其展开,最后得到给定公式的主析(合)取范式。

    现在我们要讨论指派与两种范式之间的联系。

    很明白,要使主析取范式取值1,只要使其一个合取子句取值1,从而须使这一子句中的每个文字都取值1,即令正文字中命题变元取值1,而令负文字中命题变元取值0。换言之,由主析取范式的一个合取子句可确定一个弄真原公式的指派;反之,亦可由弄真原公式的一个指派确定其主析取范式中的一个合取子句。弄真公式的指派与主析取范式的合取子句是一一对应的。例如,例1.23中公式的主析取范式有五个合取子句,它们分别对应于5个弄真公式的指派:

            p∧q∧r                1,1,1

                p∧q∧┐r              1,1,0

                p∧┐q∧r              1,0,1

                ┐p∧q∧r              0,1,1

                ┐p∧┐q∧r            0,0,1

        类似地,要使主合取范式取值0,只要使其一个析取子句取值0,从而须使析取子句中的每一文字取值0,即令正文字中命题变元取值0,而令负文字中命题变元取值1。换言之,由主合取范式的一个析取子句可确定一个弄假原公式的指派;反之,亦可由弄假原公式的一个指派确定其主合取范式中的一个析取子句。弄假公式的指派与主合取范式的析取子句是一一对应的,只是对应方式刚好相反,正文字对应0,负文字都对应1。例如,例1.23中公式的三个析取子句,如下对应于三个弄假指派:

    p∨q∨r                0,0,0

                p∨┐q∨r              0,1,0

                ┐p∨q∨r              1,0,0

        由以上分析,我们可以进一步得到下述结论:

        (1)每公式的主析取范式和主合取范式都是唯一确定的,因为任一公式的弄真指派及弄假指派是完全确定的。

        (2)永真式,例如p∨┐p,没有主合取范式,因为它没有弄假指派。永真式只有主析取范式,它包含所有可能的合取子句(p∨┐p的主析取范式为其自身),因为一切指派均弄真它。为讨论方便,约定永真式的主合取范式为t。

        (3)永假式,例如p∧┐p,没有主析取范式,因为它没有弄真指派。永假式只有主合取范式,它包含所有可能的析取子句(p∧┐p的主合取范式为自身),因为一切指派均弄假它。为讨论方便,约定永假式的主析取范式为f。

    (4)n个命题变元的主析取范式及主合取范式都有 个,因为不同的合取子句及析取子句都是 个,而两种主范式都是从 个子句中取若干个(0,1,…, 个)子句组成的(取0个子句组成t或f)。我们知道 + + … + = 。从真值表的角度看也是如此。一张真值表(确定了弄真指派和弄假指派)恰对应一个主析(合)取范式。因此,n个变元的真值表有多少种,便相应地有多少n个变元的主析(合)取范式。事实上,n个变元的真值表必有 行,对应于 个可能的指派,而最后一列的每一行有0,1两个可能的值,因而这一列可能的取值状况有 种,从而生成 张不同的真值表。

    (5)由于每一公式均有主析(合)取范式,因此,无限多的含n个变元的公式可以分作 (有限)个类,这一类公式都逻辑等价于它们共同的主析(合)取范式。

    展开全文
  • 关于离散数学中主合取与主析取范式的实现,主要通过c++实现
  • 主析取范式主合取范式

    千次阅读 2021-04-06 15:31:04
    主析取范式 小项 是n个命题变元的合取式,其中每个变元必出现且仅出现一次(以本身或否定形式),称这个合取式为小项 例:含有两个变元的小项 P ^ Q , P ^ !Q , !P ^ Q , !P ^ !Q 若有n个变元,则有2的n次方个小项 ...

    主析取范式

    小项

    是n个命题变元的合取式,其中每个变元必出现且仅出现一次(以本身或否定形式),称这个合取式为小项

    例:含有两个变元的小项

    P ^ Q , P ^ !Q , !P ^ Q , !P ^ !Q

    若有n个变元,则有2的n次方个小项

    小项编码:

    -含有n个变元的小项的角标用n位二进制码表示。

    -变元按字母次序排列

    -用1表示变元本身,0表示变元的否定形式。

    例:m00 <=> !P^!Q , m01 <=> !P ^ Q

    ​ m101 <=> P!QR m100 <=> P!Q!R

    当列出小项的真值表的时候就会发现,只有真值与小项的下标相同时,小项才为真,其余都为假。

    全体小项的析取式位永真式,记为:

    Σmi <=> m0 V m1 V… Vm2n-1(2的n次方减一) <=>T

    **主析取范式定义:**若一个命题公式的析取范式为A1 V A2 V … V An(n>=1),其中每个Ai(i=1,2,…n)都是小项,则称之为该命题公式的主析取范式

    主析取范式求法:

    1. 先写出给定公式的析取范式 A1 V A2 V … V An
    2. 为使每个Ai都变成小项,对缺少变元的项Ai要补全变元,比如缺变元R,就用“^(R V !R)”的形式补R。
    3. 用分配律等公式加以整理

    主合取范式

    **大项:**是n个命题变元的析取式,其中每个变元必出现且仅出现一次(以本身或否定形式),称该析取式为大项。

    大项的编码:大项的编码真好与小项相反

    用0表示变元本身,1表示变元的否定形式

    如:M00 <=>P V Q M01 <=> P V !Q

    ​ M101 <=> !P V Q V !R

    每个大项当且仅当其赋值与编码相同时,其真值为F,其余都为T,全体大项的合取式必为永假式。

    主合取范式定义:若一个命题公式的析取范式为A1 ^ A2 ^ … ^ An(n>=1),其中每个Ai(i=1,2,…n)都是大项,则称之为该命题公式的主合取范式

    主合取范式求法:

    1. 先写出给定公式的合取范式 A1 ^ A2 ^ … ^ An
    2. 为使每个Ai都变成大项,对缺少变元的项Ai要补全变元,比如缺变元R,就用“v(R ^ !R)”的形式补R。
    3. 用分配律等公式加以整理

    在真值表中,一个使公式的真值为F的赋值所对应的大项的析取,即为此公式的主合取范式。

    展开全文
  • 了解一下简单析取式和简单合取...而主合取和主析取略微有些不同,主析取是由极小项及符号v组成,极小项就是简单合取式,说白了主析取就是由符号v连接几个简单合取式组成,且他的每一个构成单位(极小项)的命题变项...
  • 主析取范式主合取范式原理探究

    千次阅读 2021-03-24 09:01:46
    对任意一个命题公式来说,主析取范式主合取范式都是唯一的。 命题变元指原子化的,P,Q命题。 极小项的定义:包含全部N个命题变元的合取式,称其为极小项,且N个命题变元中,每个变元与它的否定不能同时存在,但...
  • 主析取范式主合取范式

    千次阅读 2021-06-22 20:47:13
    据定义,公式┐p→┐(p→q)的主析取范式是(p∧q)∨(p∧┐q),而其主合取范式则应是(p∨q)∧(p∨┐q)。 例 求公式(p∧q)∨r的主析取范式主合取范式。 (p∧q)∨r (p∧q∧(r∨┐r))∨((p∨┐p)∧(q∨┐q)∧r) (p∧q∧...
  • 离散数学主析取主合取范式

    万次阅读 多人点赞 2019-12-06 23:11:56
    离散数学主析取主合取范式 ...文章目录离散数学主析取主合取范式**概念**一:析取范式与合取范式析取范式与合取范式求范式的步骤二:主析取主合取范式**解法**等价公式真值表注: 概念 一:析取...
  • 例, 求公式(p∧q)∨r的主析取范式主合取范式.主析取范式:(p∧q)∨r(p∧q∧(r∨┐r))∨((p∨┐p)∧(q∨┐q)∧r)(p∧q∧r)∨(p∧q∧┐r)∨(p∧q∧r)∨(p∧┐q∧r)∨(┐p∧q∧r)∨(┐p∧┐q∧r)(p∧q∧r)∨(p∧q∧┐r...
  • 对任意一个命题公式来说,主析取范式主合取范式都是唯一的。 命题变元指原子化的,P,Q命题。 极小项的定义:包含全部N个命题变元的合取式,称其为极小项,且N个命题变元中,每个变元与它的否定不能同时存在,但...
  • 任意输入一个命题公式,计算并输出其真值表以及主析取范式主合取范式思路:大概就是将蕴含,等价,异或进行转化,然后使用eval()计算#! /usr/bin/env python3# -*- coding:utf-8 -*-sInput = '' #输入的命题公式字符...
  • cout 主析取范式为:" ; printAns(ans_vf, 'M', '|'); } void dfs(int n) { if (n == 26) { stack<char> s_s(s); stack<bool> s_t; while (!s_s.empty()) { if (s_s.top() == '&' || s_s.top() == '|...
  • 通过代码编译出的程序帮助用户求出其输入的命题公式的真值表以及主析取范式主合取范式。 要求:能够列出含三个以内变量的合式公式的真值表,并给出相应的主析取和主合取范式。
  • 1. 简单 析取 合取 式 ( 1 ) 简单合取式 ( 2 ) 简单析取式 2. 极小项 ( 1 ) 极小项 简介 ( 2 ) 极小项 说明 ( 3 ) 两个命题变项 的 极小项 ( 4 ) 三个命题变项 的 极小项 ( 5 ) 极小项 成真赋值 公式 名称 ...
  • 题目:根据给定的式子,先输出其真值表,再利用真值表法求取主析取范式以及主合取范式,输出答案。 举例:以 (P^Q) V (非P^R) 为例。 程序代码 //(P^Q) V (非P^R) //主合取范式: (非PVQV非R) ^ (非PVQVR) ^ (PV非...
  •  输入真值表(1/0),输出相应的主析取范式主合取范式。 #include #include using namespace std; int Value[10000][10000]; char Variable[7]={'-','A','B','C','D','E','F'}; class Form { public: Form...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 456
精华内容 182
关键字:

主析取范式主合取范式