最近的离散数学的一个上机作业,要求任意输入一个命题公式,求它的真值表与主析取范式和主合取范式。其中的命题连接词都是用特殊符号来表示(怕麻烦……),并最终选择使用C++来编写程序。


先贴代码:

// 五种联结词优先级 ! * + @ $ 分别代表否定 合取 析取 单条件 双条件
//"规定符号代换规则为 ┐:!  ∧:*  ∨:+  ->:@  <->:$"
//"输入应当保证命题公式合法"
#include<iostream>
#include<cstring>
#include<stdlib.h>
using namespace std;
short int IsTrue[128]; //存储为真的真值指派
bool getTrue[128][7]; //存储所有的真值指派
int loc;//表示第几个真值指派类型
bool state[27]; //表示命题变元对应的真值
void set_getTrue(){for(int i=0;i<128;i++){for(int j=0;j<7;j++){getTrue[i][j]=0;}}
}
int mi(int n){ //求2的n次幂int k=1;for(int i=0;i<n;i++){k=k*2;}return k;
}
template<class T>
class Stack{
private:int top;int maxnum;T* st;
public:Stack(){maxnum=20;top=-1;st=new T[20];}~Stack(){delete[] st;}void clean(){top=-1;}bool push(T n){top++;this->st[top]=n;}T get_top(){int k=st[top];top--;return k;}T read_top(){return st[this->top];}bool IsEmpty(){if(this->top==-1) return true;return false;}bool IsFull(){if(top+1==maxnum) return true;return false;}
};
class Calculator{
private:char InfixExp[30];char PostfixExp[30];
public:Calculator(char * exp);void getinf();void getpost();void ans(int nn);void trans();
};
void Calculator::getinf(){cout<<InfixExp<<endl;
}
void Calculator::getpost(){cout<<PostfixExp<<endl;
}
Calculator::Calculator(char * exp){strcpy(this->InfixExp,exp);for(int i=0;i<30;i++){PostfixExp[i]='\0';}
}
void Calculator::trans(){Stack<char> save;int i=0,j=0;while(this->InfixExp[i]!='\0'){if(this->InfixExp[i]>=65&&this->InfixExp[i]<=90){while(this->InfixExp[i]>=65&&this->InfixExp[i]<=90){PostfixExp[j]=this->InfixExp[i];j++; i++;}//PostfixExp[j]=' '; j++;}else{if(this->InfixExp[i]=='('||this->InfixExp[i]==')'){if(this->InfixExp[i]=='(') {save.push(this->InfixExp[i]);}else if(this->InfixExp[i]==')'){if(save.IsEmpty()){cout<<"WRONG!"<<endl;exit(0);}while(!save.IsEmpty()&&save.read_top()!='('){PostfixExp[j]=save.get_top();j++;}if(save.read_top()=='(') save.get_top();}}else{if(save.IsEmpty()){save.push(this->InfixExp[i]);}else{if(this->InfixExp[i]=='!'){char temp=save.read_top();while(temp=='!'&&temp!='('&&!save.IsEmpty()){PostfixExp[j]=save.get_top();j++;temp=save.read_top();}save.push(this->InfixExp[i]);}elseif(this->InfixExp[i]=='*'){char temp=save.read_top();while(temp!='+'&&temp!='('&&!save.IsEmpty()){PostfixExp[j]=save.get_top();j++;temp=save.read_top();}save.push(this->InfixExp[i]);}elseif(this->InfixExp[i]=='+'){char temp=save.read_top();while((temp=='*'||temp=='!')&&!save.IsEmpty()){PostfixExp[j]=save.get_top();j++;temp=save.read_top();}save.push(this->InfixExp[i]);}elseif(this->InfixExp[i]=='@'){char temp=save.read_top();while((temp=='*'||temp=='!'||temp=='+')&&!save.IsEmpty()){PostfixExp[j]=save.get_top();j++;temp=save.read_top();}save.push(this->InfixExp[i]);}elseif(this->InfixExp[i]=='$'){char temp=save.read_top();while((temp=='*'||temp=='!'||temp=='+'||temp=='@')&&!save.IsEmpty()){PostfixExp[j]=save.get_top();j++;temp=save.read_top();}save.push(this->InfixExp[i]);}}}i++;}}while(!save.IsEmpty()){PostfixExp[j]=save.get_top();j++;}PostfixExp[j]='\0';
}
void Calculator::ans(int nn){Stack<int> save_num;int i=0,j=0;int n1=0,n2=0;for(i=0;i<nn;i++){cout<<' '<<getTrue[loc][i]<<' ';}i=0;while (this->PostfixExp[i]!='\0'){if(this->PostfixExp[i]>=65&&this->PostfixExp[i]<=90){int temp=0;temp=getTrue[loc][this->PostfixExp[i]-65];i++;save_num.push(temp);//cout<<"temp="<<temp<<' ';}else if(this->PostfixExp[i]=='!'){n1=save_num.get_top();n1=1-n1;save_num.push(n1);i++;}else if(this->PostfixExp[i]=='+'||this->PostfixExp[i]=='*'||this->PostfixExp[i]=='@'||this->PostfixExp[i]=='$'){n2=save_num.get_top();n1=save_num.get_top();switch(this->PostfixExp[i]){case('+'):n1+=n2;save_num.push(n1);break;case('*'):n1*=n2;save_num.push(n1);break;case('@'):if(n1>0&&n2==0) n1=0;else n1=1;save_num.push(n1);break;case('$'):if((n1+n2>0)&&(n1*n2==0)) n1=0;else n1=1;save_num.push(n1);break;}i++;}else{i++;}}if(save_num.read_top()>0) IsTrue[loc]=1;else IsTrue[loc]=0;//cout<<"ans="<<save_num.get_top()<<endl;cout<<"  "<<save_num.get_top()<<endl;
}
void printxiqu(int num,int m){int i,j;int temp=m;cout<<"主析取范式: ";for(;temp>0&&!IsTrue[temp];temp--)m=temp;for(i=0;i<m-1;i++){if(IsTrue[i]==1){cout<<'(';for(j=0;j<num-1;j++){if(getTrue[i][j]==0) cout<<"┐";cout<<(char)(j+65);cout<<"∧";}if(getTrue[i][num-1]==0) cout<<"┐";cout<<(char)(j+65);cout<<')';cout<<"∨";}}i=m-1;if(IsTrue[i]==1){cout<<'(';for(j=0;j<num-1;j++){if(getTrue[i][j]==0) cout<<"┐";cout<<(char)(j+65);cout<<"∧";}if(getTrue[i][num-1]==0) cout<<"┐";cout<<(char)(j+65);cout<<')';}cout<<endl;
}
void printhequ(int num,int m){int i,j;int temp=m;cout<<"主合取范式: ";for(;temp>0&&IsTrue[temp];temp--)m=temp;for(i=0;i<m-1;i++){if(IsTrue[i]==0){cout<<'(';for(j=0;j<num-1;j++){if(getTrue[i][j]==1) cout<<"┐";cout<<(char)(j+65);cout<<"∨";}if(getTrue[i][num-1]==1) cout<<"┐";cout<<(char)(j+65);cout<<')';cout<<"∧";}}i=m-1;if(IsTrue[i]==0){cout<<'(';for(j=0;j<num-1;j++){if(getTrue[i][j]==1) cout<<"┐";cout<<(char)(j+65);cout<<"∨";}if(getTrue[i][num-1]==1) cout<<"┐";cout<<(char)(j+65);cout<<')';}cout<<endl;
}
int main(){for(int i=0;i<27;i++) state[i]=0;for(int i=0;i<128;i++) IsTrue[i]=-1;set_getTrue();int i,j,k,m=1;int num;//命题变元的数目cout<<"输入命题公式中所含变元的数目:";cin>>num;for(i=0;i<num;i++) m=m*2;char exp[30];cout<<"输入命题公式,且应当变元从A开始使用:";cin>>exp; //命题公式Calculator cal(exp);cal.trans();//cal.getpost();for(i=0;i<m;i++){int temp=i,tt=0;for(j=0;j<num-1;j++){ //决定第j个命题变元的取值为0或1tt=mi(num-1-j); //cout<<"tt="<<tt<<endl;state[j]=temp/tt;temp=temp%tt;}state[num-1]=temp;for(int k=0;k<num;k++){getTrue[i][k]=state[k];}}for(i=0;i<m;i++){for(j=0;j<num;j++){state[j]=getTrue[i][j];}}//真值表表头for(i=0;i<num;i++){cout<<' '<<(char)(i+65)<<' ';}cout<<' '<<exp;cout<<endl;for(i=0;i<m;i++){loc=i;cal.ans(num);}printxiqu(num,m);printhequ(num,m);return 0;
}
//┐ ∧ ∨

然后说一下自己当时的思路:

首先将命题公式看作是一个数学算式一样,针对每一个命题变元的不同取值都会有对应的真值,这一计算过程相当于先将前缀表达式转后缀表达式,然后计算后缀表达式的值,用到了栈,这方面知识可以在网上找到,下面是具体链接(侵删):

https://blog.csdn.net/walkerkalr/article/details/22798365 前缀、中缀、后缀表达式转换详解

https://blog.csdn.net/xiaoniba1024/article/details/6575523 后缀表达式的求值的算法

像刚才说的那样,计算每一个命题变元取不同真值(0或1)时命题公式的真值,用一个二维数组存储命题变元的取值,用另一个一维数组存储不同的命题变元组合对应计算得出的的命题公式的真值。

真值表的话直接按照格式输出每一种命题变元的取值方式对应的命题公式的真值即可。

求主范式的步骤:由相关的数学知识可知,每一组能够使得命题公式真值为1的命题变元的取值都对应主析取范式中的一组极小值,这样可以求出主合取范式。之后利用主合取范式与主析取范式之间的关系,知余下的命题变元的取值组合就对应着主合取范式中的每一组极大值。最终从二维数组中读取命题变元的取值,按照规则输出为主析取范式与主合取范式。

然后问题解决,稍微注意一下输出格式即可。

觉得这就是一个中缀转后缀,后缀求值的问题,只不过跟数学知识联系了起来,多做了一些处理而已。

(第一次写博客,可能说不清楚事情,望见谅。如内容有错误,还请耐心指出,我会及时改正)

使用C++求命题公式的主析取范式与主合取范式相关推荐

  1. 离散数学 求命题公式的主析取范式和主合取范式

    Description 输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式. Input 命题公式的合式公式 Output 公式的主析取范式和主合取范式,输出形式为:&qu ...

  2. 离散数学——用c/c++求命题公式的主范式

    本文借鉴了这篇文章https://blog.csdn.net/DaDaMr_X/article/details/51265230 离散数学又被称为计算机数学,本篇文章就介绍了如何用C++实现求离散数学 ...

  3. 求主析取范式与主合取范式

    定义设A为恰含命题变元p1,-,pn的公式.公式A称为A的主析(合)取范式(majordisjunctive(conjunctive)normal form),如果A是A的析(合)取范式,并且其每个合 ...

  4. 【离散数学】Java语言实现利用真值表法求主析取范式和主合取范式

    C++版本的看这个链接: [离散数学]C++语言实现利用真值表法求主析取范式和主合取范式_zhtstar的博客-CSDN博客https://blog.csdn.net/weixin_56319483/ ...

  5. 【离散数学】C++语言实现利用真值表法求主析取范式和主合取范式

    Java版本的如下链接所示: Java语言实现利用真值表法求主析取范式和主合取范式_zhtstar的博客-CSDN博客https://blog.csdn.net/weixin_56319483/art ...

  6. 离散数学范式c语言实验报告,离散数学实验报告-利用真值表法求主析取范式及主合取范式的实现...

    1.实 验 报 告( / 学年 第 一 学期)课程名称离散数学实验名称利用真值表法求主析取范式及主合取范式的实现实验时间年月日指导单位指导教师学生姓名班级学号学院(系)专 业 实 验 报 告实验名称利 ...

  7. 离散实验 真值表求主析取范式、主合取范式的计算机语言实现

    离散数学 实验一 标题:真值表求主析取范式.主合取范式的计算机语言实现 其他课程的一些其他实验源码也可在本人github主页找到哦 链接如下:https://github.com/Schiz0mani ...

  8. 离散数学实践一编程判断主析取范式和主合取范式【java实现】

    文章目录 实验要求 二 编程思路分析 困难所在 二 完整代码 实验要求 实验类型:设计性 实验目的 通过算法设计并编程实现,使学生掌握利用计算机语言判别合式公式主范式的基本方法. 实验内容 给定合式公 ...

  9. 求命题公式的真值表及主范式(栈实现)

    设计思路 首先用一个串来储存使用者所输入的命题表达式,依据人类的思维,会对输入的命题公式进行分析和计算,但计算机可不会,这时我们就要写入相关代码把使用者输入的命题表达式转换为计算机所能进行计算的后缀表 ...

最新文章

  1. 论文速递:智能作为信息处理系统
  2. PMBOK第七版,通往项目管理的新地图
  3. Colored Sticks--POJ 2513
  4. java中volatile的使用方式
  5. java与java ee_Java EE拦截器
  6. vs不一致的行尾对话框怎么调出_SolidWorks工程图打开后图纸没有了空白了怎么办?还能找回来吗?...
  7. nginx请求转发被拒绝_nginx反向代理(请求转发-URL匹配规则)
  8. 列注释_【EXCEL检查问题】:如何快速检查并删除EXCEL中隐藏的工作表、行、列等信息...
  9. bug君你好啊之访问servlet时出现此程序可以连接到 Web 服务器,但是因为地址问题无法找到该网页。
  10. 用Redis实现分布式锁 与 实现任务队列
  11. MapReduce官方案例wordcount
  12. 如何用iso文件制作U盘启动
  13. 网线制作和交换机工作原理
  14. 【学习OpenCV】使用OpenCV播放AVI视频
  15. LR之识别图片验证码
  16. sklearn机器学习:岭回归Ridge
  17. 安装navicat missing required library xxx.dll(libcc.dll libdd.dll)亲测有效
  18. 害虫防治技术有哪些?
  19. 2019杭州(准)独角兽企业
  20. 处理器的排名_waste waltz家用垃圾处理器排名图片

热门文章

  1. delphi 数字转字符串补全
  2. Java Integer128陷阱详解
  3. AES128加解密流程详细介绍
  4. c语言斐波那契数列_从数学角度浅谈斐波那契数列
  5. 中国移动互联在黎明之前
  6. 经典相关分析,典型关分析, CCA,Canonical Correlation Analysis,多元变量分析,线性组合,相关系数最大化...
  7. SQL map自动注入,利用工具注入
  8. Ubuntu 安装 Mysql【详细步骤】
  9. SPSS聚类分析(含k-均值聚类,系统聚类和二阶聚类)
  10. 【案例】前端对接LED设备发送指令