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

离散数学的命题公式 ,真值表 ,主析取范式的c++代码 命题公式 ,真值表 ,主析取范式 阅读详情

本文借鉴了这篇文章https://blog.youkuaiyun.com/DaDaMr_X/article/details/51265230
离散数学又被称为计算机数学,本篇文章就介绍了如何用C++实现求离散数学中的主范式
要求主范式,具体可分为以下几步操作:
首先,由于某些特殊符号不好在计算机中打出,因此需要用相应的符号代替,并定义各个运算符的优先级,如下

替换方式
现符号优先级
非!5
合取&4
析取|3
条件-2
双条件+1

接下来需要按运算符优先级对公式进行转换,然后用位运算的方式写出五种运算符的运算方法
假设有两个命题变元a,b(计算时a,b的值为0或1),下面列出位运算方法(可以举例子试一下):
非运算:非a:  return (a+1)&1;(例如,a为1,a+1=2, 2在二进制中的表示为10,而位运算是取二进制形式的最后一位数进行运算,则为0&1,
其结果显然为0,即返回值为0,达到了非a的运算效果,以下运算方式类似)
合取:a&b: return a*b;
析取:if(a+b) return 1;else return 0;
条件:if(a==1 && b==0) return 0;else return 1;
双条件:return !((a+b)&1);

然后需要写一个函数来对所有存在的命题变元进行赋值,每个命题变元都有0和1两种情况,这一步可以采用递归来写(具体见代码),每完成一组赋值后都要都要以该组赋值情况确定下标(例如,有a,b,c,三个命题变元,假设某组赋值为101,则其下标为1*(2^0)+1*(2^2)=5,则最后输出范式时下标就为m5或M5,至于是主析取范式还是主合取范式则需看该组赋值的运算结果)

具体内容见代码:

#include<bits/stdc++.h>
using namespace std;

/*注意: 
    非:!
	合取:&
	析取:|
	条件:-
	双条件:+ 
	命题字母小写 
*/

const int N=1e4;
char s[N];//存放初始字符串 
bool table[30];//标记命题变元是否存在 
int explain[30];//存放每个命题变元的赋值(0或1) 
int value[1000010];//存放每组赋值的最后运算结果 
int sum=0;//下标 
 
int youxian(char c){
	switch(c){//定义运算符的优先顺序 
		case '#':return -1;
		case '!':return 5;
		case '&':return 4;
		case '|':return 3;
		case '-':return 2;
		case '+':return 1;
		case '(':return 0;
		default:return 0;
	}
}

void get_chars(){//将输入的字符串转换为逆波兰式 
	char post[N]={'\0'};int po=-1;//post存放转换后的命题形式,初始化为\0使strlen求长度时准确 
	char stack[N]={'#'};int st=0;//stack暂时存放运算符 
	int len=strlen(s);
	for(int i=0;i<len;i++){//当该字符为命题字母时 ,直接存入post 
		if(s[i]>='a' && s[i]<='z'){
			post[++po]=s[i];
			continue;
		}
		if(s[i]=='!'||s[i]=='&'||s[i]=='|'||s[i]=='-'||s[i]=='+'){
			/*下面一行包含两种情况,一是当前运算符优先级比上一个的小,则先把上一个运算符存入post,再把当前
			运算符暂时存入stack,以便下次比较,二是两个运算符优先级相同,则按从左到右的顺序运算,操作和第一
			种情况相同,还有一种运算符优先级大于上一个的情况,在60行得到了处理*/ 
			while(youxian(s[i])<=youxian(stack[st])) post[++po]=stack[st--];
			stack[++st]=s[i];
			continue;
		}
		if(s[i]=='('){
			stack[++st]=s[i];
			continue;
		}
		if(s[i]==')'){
			while(stack[st]!='(') post[++po]=stack[st--];//把括号之间的运算符加到post里 
			st--;//完成了一个括号内所有字符转换后,将st重新返回0,为后面的转换做准备 
			continue;
		}
	}
	while(st) post[++po]=stack[st--];/*该操作主要处理运算符优先级大于上一个的情况,把之前存在stack里
	的运算符一一存入post,至此,已完成全部字符串转换为逆波兰式的操作*/ 
	strcpy(s,post);//由于post不是全局变量,所以需要复制给s
	int l=strlen(s);
}
	
void settable(){//统计命题变元的个数 
	memset(table,0,sizeof(table));//将table数组初始化为0 
	int len=strlen(s);
	for(int i=0;i<len;i++){
		if(s[i]>='a'&&s[i]<='z') table[s[i]-'a']=true;//若含有某个变元,则将对应的table值变为1 
	}
	for(int i=0;i<26;i++){
		if(table[i]) sum++;//求命题变元的个数 
	}
	sum=pow(2,sum);//一共2^ans个赋值情况 
}

int boti(){//计算下标,如010表示2 
	int sum=0,wei=1;
	for(int i=25;i>=0;i--){//从后往前依次成二倍相加,把二进制数转换为十进制数 
		if(table[i]){
			if(explain[i]){ 
			    sum+=wei;/*expaain值为0时不需要加,只需加上1对应的值即可
			    如10010为1*2+1*2^4=20 */ 
		    }   wei*=2;
		}
	}
	return sum;//sum为最大情况个数 
} 

int cal(int a,int b,char c){//采用位运算对四种运算符进行操作 
	switch(c){
		case'&':return a*b;//合取 
		case'|':if(a+b) return 1;else return 0;//析取 
		case'-':if(a==1 && b==0) return 0;else return 1;//条件,a为真,b为假时为0,其他都为1; 
		case'+':return !((a+b)&1);//按位运算,比如2的二进制为10,则选0&1为结果 
	}
} 

int work(){//按照逆波兰式两两结合计算出最后结果 
	int stack[N],st=-1;
	int len=strlen(s);
	for(int i=0;i<len;i++){
		if(s[i]>='a' && s[i]<='z'){
			stack[++st]=explain[s[i]-'a'];//存入命题的一次赋值(为0或1) 
			continue;
		}
		if(s[i]=='!'){//是!时对上一个字符取非 
			stack[st]=(stack[st]+1)&1;//位运算:+1后再跟1进行与运算可实现非的效果 
			continue;
	    }
	    int ans=cal(stack[st-1],stack[st],s[i]);//两两结合运算 
	    stack[--st]=ans;//每次将st归零 ,下次将stack[0]与stack[1]运算 
	}
	return stack[0];//返回的是最终运算后的结果 
} 

void assign(){//计算一组赋值后的结果,如00010,10100对应的结果 
	int x=boti();
	int ans=work();
	value[x]=ans;
}
void generate(char c){//利用真值表列出所有的取值情况 
	while(c<='z'&&table[c-'a']==false) c++;//因为命题字母可以随意选择,所以要把26个遍历一遍 
	if(c>'z'){//超出z后再计算该组赋值的结果 
		assign();
		return ;
    }
    explain[c-'a']=0;//类似树状图,遍历所有命题变元的0,1取值 
    generate(c+1);
    explain[c-'a']=1;
    generate(c+1); 
}

void output1(){//输出析取范式 
	int i=0;
	while(i<sum && !value[i]) i++;/*此处sum可理解为最大情况总数, 
	在generate函数中每组数据以sum为下标都有对应的value[sum]值 
	*/ 
	if(i >= sum){
		printf("无主析取范式\n");
		return ;
	}
	printf("主析取范式为:m%d",i);
	for(i++;i<sum;i++){
		if(value[i]) printf(" V m%d",i);
	}
	printf("\n");
}

void output2(){//输出合取范式 
	int i=0;
	while(i<sum && value[i]) i++;
	if(i >= sum){
		printf("无主合取范式\n");
		return ;
	}
	printf("主合取范式为:M%d",i);
	for(i++;i<sum;i++){
		if(!value[i]) printf(" ∧ M%d",i);
	}
	printf("\n");
}

int main(){
	cin>>s;
	get_chars();
	settable();
	memset(value,0,sizeof(value));
	memset(explain,0,sizeof(explain));
	generate('a');//从a开始遍历26个字母 
	output1();
	output2();
	return 0;
}

测试样例如下:

离散数学 求命题公式的主范式 实现功能:输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式。 输入:命题公式的合式公式 输出:公式的主析取范式和主析取范式,输出形式为:“ mi ∨ mj ; Mi ∧ Mj” ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用“ ; ”隔开,“ ; ”前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范 阅读详情

相关推荐

当年明月在,曾照彩云归

彩云

宝藏Coder的空间 1232

命题逻辑中的主范式的求解(c语言实现)

在求解命题逻辑中主范式的时候,对于输入的式子(字符串)的处理极其重要,这关系到范式的求解的成功与否。 输入的公式如:p->q,计算机并不“认识”这种式子。因而可以将其转化为后缀式(逆波兰式):pq->,让计算机按照它的方式扫描、计算。同时实现此求解的过程还需要将一些十进制的数据转换为二进制,和一些小技巧。废话不多说,代码如下: #include <stdio.h> #include <string.h> //合取符号 & ;析取符号 |; //...

dou2629531529的博客 2908

echarts实现3D地图——map3D

【代码】echarts实现3D地图——map3D。

xiaoququ的博客 7324

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

/*实现功能:输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式。输入:命题公式的合式公式输出:公式的主析取范式和主析取范式,输出形式为:“ mi ∨ mj ; Mi ∧ Mj” ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用“ ; ”隔开,“ ; ”前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范式为...

weixin_36284848的博客 2156

未隔离电源设备使用usb转串口调试导致串口模块爆炸烧坏事故记录

这个事就发生在前两天,我们公司的wifi模块被客户用到了咖啡机上,客户寄了一台整机给我们协助调试,还送了几包咖啡豆,本想着还能打个咖啡喝一喝的,但就在咖啡机刚寄过来第一天,就出事了。而这个事故的发生,竟然仅仅是因为同事接了个串口模块到电脑调试打印导致的。谁也想不到,这个3.3V的供电的wifi模块居然还有这么大的威力。直接将usb转TTL串口模块的转换芯片给爆开了,咖啡机也给弄坏了,据同事描述当时情况就只见到一片火光和一声巨响,状况比较惨烈,所幸的是笔记本电脑没有烧坏,但是直接给崩蓝屏了。 ...

fangye945a的博客 6197

开漏输出(漏极开路输出与集电极开路输出)和推挽输出怎么判断

判断一个引脚是还是。

weixin_56838517的博客 1058

离散数学求命题公式的主范式的C++实现

本文章代码部分转载https://blog.youkuaiyun.com/DaDaMr_X/article/details/51265230 我增加了较多的注释,便于大家更好的理解 由于命题公式的很多符号我们无法从键盘录入,因此用以下做替换 ! 非,替换 “ ¬ ” & 与,替换 “ ∧ ” | 或,替换“ ∨ ” - 蕴含,替换“ → ” + 等价联结词,替换“ ↔ ” #include <cstdio> #include <cstring> #include <c..

Soul__man的博客 2334

Java全栈:电影数据检索与推荐系统实战

全文检索个性化推荐数据缓存容器化部署通过这个项目,我们不仅实践了Java全栈开发的各项技术,还接触了推荐系统的核心算法实现。用户历史行为数据物品特征数据上下文信息实时反馈算法的准确性推荐的多样性系统的实时性冷启动问题性能优化效果评估VIEW, // 浏览CLICK, // 点击SEARCH, // 搜索RATE, // 评分COMMENT, // 评论SHARE, // 分享WATCH_TIME, // 观看时长。

exlink2012的专栏 892

北理工离散数学上机实验:求命题公式的主范式

题目要求: 实现功能:输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式。 输入:命题公式的合式公式 输出:公式的主析取范式和主析取范式,输出形式为:“ mi ∨ mj ; Mi ∧ Mj” ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用“ ; ”隔开,“ ; ”前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范式为 0 。 输入公式的符号说明: ! 非,相当于书面符号中的 “ ¬ ” &a...

weixin_52425243的博客 2788

Android Audio最全面试题及参考答案(7万字长文)

在 Android 音频系统中,应用通过框架层的 API 发出音频请求,这些请求经过音频服务层的处理,传递到 HAL 层,再由 HAL 层调用音频驱动层与硬件进行交互,最终实现音频的播放、录制等功能。在 Android 音频系统中,应用通过框架层的 API 发出音频请求,这些请求经过音频服务层的处理,传递到 HAL 层,再由 HAL 层调用音频驱动层与硬件进行交互,最终实现音频的播放、录制等功能。音频播放完成事件:当使用 MediaPlayer 等音频播放类播放音频时,音频播放完成后会触发这个事件。

大模型大数据攻城狮的专栏 2605

GEE:面对对象土地利用分类(结合SNIC、GLCM 和机器学习算法)

本文将介绍在Google Earth Engine中结合SNIC、GLCM和机器学习算法的的土地利用/土地覆盖(LULC)分类方法。结果如下图所示,

养乐多的博客 5619

c语言编程求主合取范式,求给定命题公式真值表并根据真值表求公式主范式.doc...

“离散数学”实验报告(求给定命题公式的真值表一.实验目的3二.实验内容……………………………………………………………………….3求任意一个命题公式的真值表3三.实验环境3四. 实验原理和实现过程(算法描述)31.实验原理32.实验流程图5五.实验代码6六. 实验结果14七. 实验总结19一.实验目的本实验课程是网络工程专业学生的一门专业基础课程,通过实验,帮助学生更好地掌握计算机科学技术常用的离散...

weixin_36321633的博客 2432

SAP 系统里生成 PDF 的几条主干路径:从 Spool 转换到 Adobe 原生渲染,再到 BTP 云服务

本文系统梳理了SAP生态中PDF生成的多种技术方案,包括Spool转换、OTF转换、Smart Forms/Adobe Forms原生生成以及云端服务等不同路径。文章通过实际案例和代码示例,详细分析了各方案的适用场景、技术要点和工程实践建议,特别强调了多语言支持、字体处理、性能优化等关键因素。针对不同业务需求,提供了从简单导出到复杂交互式PDF的完整解决方案框架,为SAP环境下的PDF处理提供了实用指南。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 293

【北理离散数学】求命题公式的主范式

​本文主要实现了求命题公式的主范式 借鉴了离散数学——用c/c++求命题公式的主范式_c++命题公式的范式-优快云博客的做法,先读入公式,转换为逆波兰式,然后统计变量个数,随后对公式边赋值边计算,并将计算的结果存入到value数组中,最后进行输出。难点在于逆波兰式的转换、计算;递归赋值;如何一边赋值一边计算然后储存;自定义逻辑运算符。

2303_80834338的博客 700

【云原生系列】第一讲:什么是云计算

云计算(cloud computing):分布式:分布式计算的一种,指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,合并&反馈:通过多部服务器组成的系统进行处理和分析这些小程序得到结果并返回给用户。云计算早期:分布式计算:简单的分布式计算,解决任务分发,并进行计算结果的合并。因而,云计算又称为网格计算。通过分布式计算,可以在很短的时间内(几秒钟)完成对数以万计的数据的处理,从而达到强大的网络服务。现阶段:计算:分布式计算、效用计算、负载均衡、并行计算、存储。

颜淡慕潇 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

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

最近的离散数学的一个上机作业,要求任意输入一个命题公式,求它的真值表与主析取范式和主合取范式。其中的命题连接词都是用特殊符号来表示(怕麻烦……),并最终选择使用C++来编写程序。 先贴代码: // 五种联结词优先级 ! * + @ $ 分别代表否定 合取 析取 单条件 双条件 //"规定符号代换规则为 ┐:! ∧:* ∨:+ -&gt;:@ &lt;-&gt;:$" //"输入应当保...

ForAxel的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

离散数学,命题公式(真值表+范式(析&&主))

//此代码只支持三个变相的命题公式 #include<iostream> #include<cctype> #include<set> #include<string> #include<stack> using namespace std; int Com(char a) { switch (a) { case '(':retur...

qq_44555205的博客 4604

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

离散数学实验三则(关系元算,集合运算与操作,最短路)

前言 前段时间才做了离散实验的实验报告,为防止在本地遗失,所以上传到优快云上一份,欢迎大家一起学习 实验1 关系元算 实验报告内容 一、实验目的 熟悉掌握命题逻辑中的联结词、真值表、主范式等,进一步能用他们来解决实际问题。 二、实验内容 1、从键盘输入两个命题变元P和Q的真值,求它们的合取、析取、条件和双条件的真值。(A) 2、求任意一个命题公式的真值表(B,并根据真值表求主范式(C)) 三、实验环境 C或C++语言编程环境实现。 DEVC++ 5.4.0 MinGW GCC 4.7

m0_61126523的博客 2865

离散实验模板

南京工程学院实验报告 课程名称离散数学 项目名称命题逻辑 实验学生班级K多媒体111 实验学生姓名朱在吉 学    号240111338 同组学生姓名 实验时间2...

weixin_30746117的博客 511

[离散] 打印任意命题公示的真值表和主范式

课本是高等教育出版社出版的《离散数学及其应用》。 程序会自动分析输入的表达式,并且列出真值表,最后打印出主析取范式和主合取范式,最多支持256 个变元。 主要用到的算法:中缀表达式转后缀表达式、后缀表达式求值还有一个二进制加法模拟。 下面上2 个图,第一个是表达式开头没有非运算的(课本P85 例3.5.5): 第二个不但表达式开头有非运算,而且非运算之后并不是一个数值,而是一个...

dawuafang 853

c语言编程输出主析取范式,c++编程:从键盘上任意输入一个主析取范式,输出与之等值的主合取范式...

满意答案zxuu112013.09.15采纳率:44%等级:8已帮助:2365人//从键盘上任意输入一个主析取范式,输出与之等值的主合取范式。┐∧∨# include # include # include using namespace std ;//跳出函数bool jump(const char ch){char c = cin.peek() ;if (ch == ')' &...

weixin_28854085的博客 1231

[离散数学]使用c++写一个逻辑运算计算器

用c++和visual studio 2022实现一个离散数学真值表的打印,无论输入的命题是否带有括号,都能进行计算。点开看看,说不一定是你需要的呢乁( ˙ ω˙乁)

m0_74166068的博客 1717

C/C++实现对输入的命题条件表达式输出其所有成真赋值

整理东西发现早先用C/C++写的一份代码,用到了栈数据结构,想想应该可以贴出来。主要目的是输入命题,然后输出所有的成真赋 程序需要实现输入一个条件表达式,输出其所有成真赋值。 程序分为两个部分,一个是检查输入的表达式以及命题是否正确及匹配。一个是核心代码,用于求结果。根据命题个数得出不同赋值方式的的个数(认为是一组二进制数,因此以十进制保存,即若有三个命题则从 0 ~ 23 -1)再代入表...

Lazy_Sleep的博客 1823

离散数学实践(1)-编程实现利用真值表法求主析取范式以及主合取范式

本文为离散数学实践作业之编程实现“利用真值表法求主析取范式以及主合取范式”,为有需要的同学提供参考

wyd_333的博客 4211

离散数学期末复习-求主范式

文章目录析取范式与合取范式定义简单析取式析取式简单合取式合取式析取范式合取范式范式公式A的析取范式公式A的合取范式命题公式的范式求公式A的范式的步骤求公式的范式举例极大项与极小项定义主析取范式与主合取范式主析取范式主合取范式举个例子A的主析取范式A的主合取范式定理求公式的主范式用等值演算法求公式的主范式的步骤例题主范式的用途--与真值表相同(1)求公式的成真赋值和成假赋值(2)判断公式的类型(3)判断两个公式是否等值(4) 析取范式与合取范式 定义 命题变项及其否定的总称 简单析取式 有限个文字构成的析取式

博客地址 www.sec0nd.top 9494

求命题公式的主范式

求命题公式的主范式题目信息输入输出解答想法 题目信息 输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式。 输入 命题公式的合式公式 输出 公式的主析取范式和主析取范式,输出形式为:mi ∨ mj ; Mi ∧ Mj ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用;隔开,;前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范式为 0 。 输入公式的符号说明: ! 非,相当于书面符号中的 ¬ & 与,相当于书面

zhj12399的博客 2909
上一篇: 一类简单离散数学推理题的代码实现原理
下一篇: c++实现矩阵乘法&关系矩阵乘法
Initial atom
博客等级 码龄5年 11粉丝 5原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值