离散数学

编程实现求解逻辑表达式的真值表、主析取范式、主合取范式

一:程序设计思想:

总思想可分为三部分:
1)真值表的求解:
对于一个含n个命题变元的表达式(n为相异的命题变元总个数),其真值表可看作由从0到2ⁿ-1的二进制数的变化表。因此,可以通过按行列举0到2ⁿ-1的二进制数来模拟真值表中命题变元的值。而对于表达式,在每一行,其值可通过运用该行的命题变元的值来求解。为此,应考虑:
①建立命题变元与0/1的键值对关系。可通过C++:stl::map来建立。
②理解表达式并求值。
2) 表达式求解:
对于表达式,应考虑:
①定义各个运算符的运算法则。
②定义各个运算符的优先级关系。
求解:
在求解表达式的过程中,可利用两个栈,分别存入临时读取的命题变元的值和逻辑运算符。在依次读取表达式的过程中,通过比较运算符的优先级关系,边读取边运算,并将值存入储存值的栈中。最终,读取完毕,求解完成。储存值的栈的栈顶即为逻辑表达式的值。
3)求解主合取范式、主取范式:
主合取范式: 与1)中思想类似,在输出真值表的过程中,若某行的表达式的值为0,通过该行的map中的键值对关系,按照相应的格式,将命题变元或其否定存入主合取范式的字符串中。
同理,
主析取范式:在输出真值表的过程中,若某行的表达式的值为1,通过该行的map中的键值对关系,按照相应的格式,将命题变元或其否定存入主析取范式的字符串中。
最后,一并输出两个字符串即可。

二:程序源码:

#include<string>
#include<vector>
#include<map>
#include<stack>
#include<iostream>
#include<algorithm>
#include<math.h>using namespace std;// fun1: (十进制转换为二进制) 赋真值
void fun1( int x,  map <char,int>& m){auto p = --m.end();//由于map升序排列,用迭代器p指向map的末尾 for(int i = 1; i <= distance( m.begin(), m.end()); i ++){p->second = x % 2;x = x / 2;p --;}
}//compare:用于描述运算符之间的优先级关系
int compare( char a, char b){if(a == '!') {if( b == '(') return -1;else if(b == '!') return 0;else return 1;}else if(a == '@' ){if((b == '(' || b == '!')) return -1;else return 1;}else if(a == '#') {if((b == '@'|| b == '(' || b == '!')) return -1;else return 1;}else if(a == '$' ){if((b == '@'|| b == '(' || b == '#' || b == '!')) return -1;else return 1;  }else if(a == '%'){if(( b == '%' || b == ')')) return 1;else return -1;} else if(a == '(' ){if(b == ')') return 0;else return -1;}
}//value:定义运算法则 并计算 a ? b 并返回值
int value( int a, char c, int b){if(c == '@') return a*b;//合取 if(c == '#') {if(a == 0 && b == 0) return 0;else return 1;}//析取 if(c == '$') {if(a == 1 && b == 0) return 0;else return 1;}//条件if(c == '%') {if(a == b) return 1;else return 0;}//双条件
}//key:表达式求解 利用两个栈分别存储 值和运算符 逐渐求解
int key(string s, map <char,int> m){s += ")";stack <int> s1;stack <char> s2;  s2.push('(');for(int i = 0; i != s.length(); i ++){if(isalpha(s[i])){auto p = m.find(s[i]);s1.push(p->second);}else if(isdigit(s[i])) s1.push(s[i] - '0');else {if(compare( s2.top(), s[i]) == -1) s2.push(s[i]);else if(compare( s2.top(), s[i]) == 0) s2.pop();else if(compare( s2.top(), s[i]) == 1) {if(s2.top() == '!') {int a = s1.top();  s1.pop();if(a == 1) s1.push( 0);else s1.push( 1);s2.pop();    i --;}else{int b = s1.top(); s1.pop();int a = s1.top(); s1.pop();s1.push( value( a, s2.top(), b));s2.pop();   s2.push( s[i]);}}}}return s1.top();
}//fun2:(利用真值表) 计算主合取范式和主析取范式 并存入s1, s2
void fun2(int i, int key, map <char,int> m, vector <int>& Max,vector <int>& min, string& s1, string& s2){if(key == 0) {Max.push_back(i);s1+='(';for(auto i = m.begin(); i != m.end(); i ++){if(i->second == 1) s1+='!';s1+=i->first;if(i != --m.end()) s1+='#';}s1+=')';s1+='@';}else {min.push_back(i);s2+='(';for(auto i = m.begin(); i != m.end(); i ++){if(i->second == 0) s2+='!';s2+=i->first;if(i != --m.end()) s2+='@';}s2+=')';s2+='#';}
}//print函数: 输出 主合取范式和主析取范式
void print( vector <int> Max, vector <int> min, string s1, string s2){  printf("主合取范式:\n");cout << "∏"; for(auto i = Max.begin(); i < Max.end(); i ++){if( i == Max.begin()) {cout << *i; } else cout << ", " << *i;}cout << endl;for(int i = 0; i < s1.length(); i++){if(i == s1.length() - 1) {if(s1[i] != '@') cout << s1[i];}else cout << s1[i];}cout<< endl<< endl;printf("主析取范式:\n");cout << "∑"; for(auto i = min.begin(); i < min.end(); i ++){if( i == min.begin()) {cout << *i; } else cout << ", " << *i;}cout << endl;for(int i = 0; i < s2.length(); i++){if(i == s2.length() - 1) {if(s2[i] != '#') cout << s2[i];}else cout << s2[i];}
}int main(){//声明 printf("由于合取、析取等特殊字符难以表示,故作以下声明\n");printf("声明:\n");printf("以!代替否定\n");printf("以@代替合取\n");printf("以#代替析取\n");printf("以$代替条件\n");printf("以%代替双条件\n\n");printf("支持使用括号()、支持n个命题变元、支持重复的命题变元、支持0/1参与运算\n\n");printf("请输入合法的表达式:\n->");string s;//表达式 string s1, s2;// 合取范式和主析取范式vector <int> Max, min;//集合:存储大项和小项的下标 map < char, int> m;// map<char, int>: 建立命题变元与 0/1 的键值对关系 cin >> s;cout << endl;//map: P Q R ... ...  map的初始化 for(auto i = s.begin(); i != s.end(); i ++){if(isalpha(*i)) m.insert(make_pair( *i, 0));}printf("真值表:\n");//输出真值表——表头//1 输出 键 map_keyfor(auto i = m.begin(); i != m.end(); i ++){cout << i->first << "   ";}//2 输出表达式 cout << s; cout << endl;int n = pow( 2,distance(m.begin(), m.end()));//总情况个数 //(按行依次)输出真值表——真值 for(int i = 0; i < n; i ++){//1 为键赋值 fun1( i, m);//2 输出 值 map_valuefor(auto i = m.begin(); i != m.end(); i ++)cout << i->second << "   ";//3 计算并输出表达式的真值 cout << key( s, m) << endl;//4 计算主合取范式和主析取范式 并存入s1, s2 fun2( i, key( s, m), m, Max, min, s1, s2);}cout << endl << endl;print( Max, min, s1, s2);//输出 主合取范式和主析取范式return 0; // 程序结束
}

C++实现求解逻辑表达式的真值表、主析取范式、主合取范式相关推荐

  1. 【c++】[自动生成真值表/主析取范式/主合取范式的计算器]

    关于自动生成真值表/主析取范式/主合取范式的计算器 我用c++写了一个,需要的自取,如果好用请点赞 链接:https://pan.baidu.com/s/1Ji1zPDtjAc6-TDxovEzMVw ...

  2. 离散数学:计算主析取范式(基于真值表)

    计算主析取范式 [问题描述] 请根据给定的命题公式,计算其真值为T的小项,列出主析取范式,并输出结果. [输入形式] 输入一个字符串(字符串长度<=50)形式的命题公式,以回车表示输入结束.其中 ...

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

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

  4. 【数理逻辑】范式 ( 合取范式 | 析取范式 | 大项 | 小项 | 极大项 | 极小项 | 主合取范式 | 主析取范式 | 等值演算方法求主析/合取范式 | 真值表法求主析/合取范式 )

    文章目录 一. 相关概念 1. 简单 析取 合取 式 ( 1 ) 简单合取式 ( 2 ) 简单析取式 2. 极小项 ( 1 ) 极小项 简介 ( 2 ) 极小项 说明 ( 3 ) 两个命题变项 的 极 ...

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

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

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

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

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

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

  8. 利用真值表法求取主析取范式以及主合取范式的实现(C++)

    代码如下: #include <iostream> #include <stack> #include <string> #include <vector&g ...

  9. 【离散数学】计算主析取范式(基于真值表)

    [问题描述] 请根据给定的命题公式,计算其真值为T的小项,列出主析取范式,并输出结果. [输入形式] 输入一个字符串(字符串长度<=50)形式的命题公式,以回车表示输入结束.其中的命题公式为仅包 ...

  10. 用c语言编程求主析取范式,求主析取范式.cpp · wangzhankun/C-Programming-Learn - Gitee.com...

    /* 实现功能:输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式. 输入:命题公式的合式公式 输出:公式的主析取范式和主析取范式,输出形式为:" mi ∨ mj ...

最新文章

  1. 在python中排序元组
  2. ElasticSearch 简介,概念和集成
  3. flink的Table类型的变量两种输出的形式
  4. c语言将字母的acsaii,C语言上机实验 答案
  5. php过滤多空格_php正则过滤html标签、空格、换行符的代码(附说明)
  6. 单处理机系统的进程调度实验_Chcore -- 上交IPADS操作系统银杏书配套Lab实验笔记 - Lab3进程与异常(一)...
  7. matlab中文帮助_拿走不谢,simulink,stateflow,ecoder帮助手册中英对照版首发
  8. APK的Mokey测试
  9. ClassPathResource详解
  10. 现代语音信号处理之语音信号的非线性分析
  11. c 语言条件运算符,C 语言条件运算符详细讲解
  12. PHP加密 php源代码在线加密工具推荐
  13. PHP 实现 apple 苹果快捷登录
  14. Revit二次开发2、RevitAPI、RevitAPIUI及Revit开发三大利器
  15. 2020Revit又是怎样进行正向建模的呢?适合Revit建模插件工具
  16. Module build failed: Error: ENOENT: no such file or directory, scandir node_modules\node-sass\vendor
  17. 一年级的小孩可以学习机器人编程
  18. 使用 gomonkey Mock 函数及方法时遇到 panic: permission denied 的问题及解决方法
  19. 2019年3月16日山东省事业单位统考考题及解析(综合类)
  20. 关于导出编辑后的PDF文件中目录带框的情况及解决

热门文章

  1. C语言程序设计孙家啸第一版,广东(年4月自考各专业课程使用教材.doc
  2. Insyde uefi 隐藏设置_利用rufus制作Linux/Windows安装启动盘(支持UEFI+GPT)
  3. 转帖 美国 工程索引 收录中国科技论文的最新规定
  4. K均值算法(K_means)
  5. 微信公众号视频下载教程
  6. VAST2 0视频广告投放解决方案改变视频网站未来技术格局
  7. Java中观察者模式与委托的对比
  8. 关于Java观察者模式的一点思考
  9. 设计模式【2】——责任链模式
  10. DllMain函数参数简介