您的位置:首页 > 编程语言 > C语言/C++

离散数学:验证P,Q两个逻辑表达式是否逻辑等价(C语言实现)

2014-04-27 11:28 781 查看
一、程序通过编译,并实现两个命题的各种逻辑运算

二、任意输入字符串P和Q逻辑表达式的合法性检查

三、利用真值表方法验证他们的等价性

一、算法分析

①    求任意一个命题公式的真值表,,根据真值表验证他们的等价性

C语言算法:

首先是输入一个合理的式子,然后从式子中查找出变量的个数,开辟一个二进制函数,用来生成真值表,然后用函数运算,输出结果,并根据结果归类给范式,再根据范式验证等价性。

函数部分,主要是3个函数,一个为真值表递加函数,通过二进制的加法原理递进产生,一个为分级运算函数,这个函数是通过判断括号,选出最内级括号的内容执行运算函数,这样一级一级向外运算,最后得出最终结果,剩下一个为主运算函数,按照运算符号的优先级按顺序进行运算,如先将所有非运算运算完,再执行与运算。如此运算。

②    

/**主运算函数**/
intMAP(char sz
,char ccu
,int icu
,int h0)
{
int i, h = 0, j = 0, j1 = 0, j2 = 0, j3 = 0,j4 = 0, j5 = 0, i1, i2, p1 = -1, p2 = -1, s;
char dt
;
s = strlen(sz);
if(s == 1)
if(sz[0] == -2)              //判断是否是最后一项
return0;
else
return1;         //1就是sz[0]的值、
else{
for(i = 0; i < s-j; i++) //先处理非
if(sz[i]== '!'){
for(i1 = 0; i1 < h0; i1++)
if(sz[i+1]== ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == -2)//如果是前运算结果的0,则P1等于0
p1= 0;
if(p1 == -1)//如果是数字,直接给P1
p1= sz[i+1];
dt[j+2] = !p1;//非运算
sz[i] = j+2;
j++;
p1 = 0;
for(i1 = i+1; i1 < s-j; i1++)
sz[i1]= sz[i1+1];//将后续式子前移一项
}
p1= -1;
j1= j;
for(i = 0; i < s-j1-2*j2; i++) // 处理与
if(sz[i]== '&'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1]== ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1]== ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2 = 2; i2 < j+2; i2++) {
if(sz[i-1] == i2) //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2) //如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1) //如果是数字,直接给P1
p1 = (int)(sz[i-1]);
if(p2 ==-1)//如果是数字,直接给P2
p2 = (int)(sz[i+1]);
dt[j+2] = p1 && p2;//与运算
sz[i-1] = j+2;
j++;
j2++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 < s-j1-2*j2; i1++)//将后续式子前移两项
sz[i1] = sz[i1+2];
i = i-1;
}
for(i = 0; i < s-j1-2*j2-2*j3; i++) // 处理或。
if(sz[i] == '|'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2=2;i2<j+2;i2++) {
if(sz[i-1] == i2)  //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2)//如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1)//如果是数字,直接给P1
p1 = sz[i-1];
if(p2 == -1)//如果是数字,直接给P2
p2 = sz[i+1];
dt[j+2] = p1 || p2;//或运算
sz[i-1] = j+2;
j++;
j3++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 < s-j1-2*j2-2*j3;i1++)//将后续式子前移两项
sz[i1]=sz[i1+2];
i--;
}
for(i = 0; i < s-j1-2*j2-2*j3-2*j4;i++) // 处理蕴含。
if(sz[i] == '^'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2 = 2; i2 < j+2; i2++) {
if(sz[i-1] == i2) //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2) //如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1]== -2)//如果是前运算结果的0,则P1等于0
p1 =0;
if(sz[i+1]== -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1== -1)//如果是数字,直接给P1
p1 =sz[i-1];
if(p2== -1)//如果是数字,直接给P2
p2 = sz[i+1];
dt[j+2]= (!p1) || p2;//蕴含运算
sz[i-1]= j+2;
j++;
j4++;
p1= -1;
p2= -1;
for(i1= i; i1 < s-j1-2*j2-2*j3-2*j4; i1++)//将后续式子前移两项
sz[i1] = sz[i1+2];
i--;
}
for(i = 0; i < s-j1-2*j2-2*j3-2*j4-2*j5; i++) // 处理等值。
if(sz[i] == '~'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2 = 2; i2 < j+2; i2++) {
if(sz[i-1] == i2) //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2) //如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1)//如果是数字,直接给P1
p1 = sz[i-1];
if(p2 == -1)//如果是数字,直接给P2
p2 = sz[i+1];
dt[j+2] = (!p1 || p2) && (!p2|| p1);//等值运算
sz[i-1] = j+2;
j++;
j5++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 <s-j1-2*j2-2*j3-2*j4-2*j5; i1++)//将后续式子前移两项
sz[i1] = sz[i1+2];
i--;
}
return dt[j+1];//返回结果
}
}


③     

/**分级运算函数**/
intCR(char sz
,char ccu
,int icu
,int h0)
{
int i,j,h,s,kh = 0,wz
,a;
char xs1
,ckh
;                 //xs1用来保存括号内的字符 ckh用来保存括号。
s= strlen(sz);
for(i = 0; i < s; i++)
if(sz[i] == '(' || sz[i] == ')'){   //判断括号
wz[kh]= i;                                 //存储括号位置
ckh[kh]= sz[i];                    //存储括号类型
kh++;
}
if(kh == 0)
returnMAP(sz,ccu,icu,h0);    //如果无括号,直接运行
else{
for(i= 0; i < kh; i++)
if(ckh[i] == ')')                     //找到第一个" )"
break;
for(j= wz[i-1]+1,h=0; j < wz[i]; j++,h++) //存储最内级括号中的内容
xs1[h] = sz[j];
xs1[h]= '\0';
a= MAP(xs1,ccu,icu,h0);             //运行最内级括号的式子,得到结果
if(a== 1)                                   //判断并存储结果
sz[wz[i-1]] = 1;
else
sz[wz[i-1]] = -2;
for(j= wz[i-1]+1; j < s+wz[i-1] - wz[i]; j++)//将括号后内容前移
sz[j] = sz[j + wz[i] - wz[i-1]];
sz[j]= '\0';
returnCR(sz,ccu,icu,h0);//循环执行
}
}


④     

/**二进制赋值函数**/
voidBVA(int b
,int f){
int i;
i= f;
if(b[f] == 0)       //加1
b[f]= 1;
else                   //进位
{
b[f]= 0;
BVA(b,--i);
}
}


⑤    

/**根据范式判断两个逻辑表达式是否等价**/
for(i1 = 0;i1 < h; i1++){
hq1[j] = hq[i1];
}
for(i1 = 0;i1 < h; i1++){
hq2[j] = hq[i1];
}
for(i1 = 0;i1 < h; i1++){//判断两个逻辑表达式是否等价
if(hq1[i1] != hq2[i1]){
flag = 0;
break;
}
else
flag = 1;
}
if(flag ==0)printf("\t\t#          您输入的两个逻辑表达式不等价         #\n");
else if(flag ==1)printf("\t\t#           您输入的两个逻辑表达式等价          #\n");


程序运行界面如下:









程序清单

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#include<math.h>
#define N 50
int hq
,i1,h=0;//定义全局变量

/**主运算函数**/
int MAP(char sz
,char ccu
,int icu
,int h0)
{
int i, h = 0, j = 0, j1 = 0, j2 = 0, j3 = 0, j4 = 0, j5 = 0, i1, i2, p1 = -1, p2 = -1, s;
char dt
;
s = strlen(sz);
if(s == 1)
if(sz[0] == -2)		//判断是否是最后一项
return 0;
else
return 1;		//1 就是sz[0]的值、
else{
for(i = 0; i < s-j; i++) //先处理非
if(sz[i] == '!'){
for(i1 = 0; i1 < h0; i1++)
if(sz[i+1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(p1 == -1)//如果是数字,直接给P1
p1 = sz[i+1];
dt[j+2] = !p1;//非运算
sz[i] = j+2;
j++;
p1 = 0;
for(i1 = i+1; i1 < s-j; i1++)
sz[i1] = sz[i1+1];//将后续式子前移一项
}
p1 = -1;
j1 = j;
for(i = 0; i < s-j1-2*j2; i++) // 处理与
if(sz[i] == '&'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2 = 2; i2 < j+2; i2++) {
if(sz[i-1] == i2) //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2) //如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1) //如果是数字,直接给P1
p1 = (int)(sz[i-1]);
if(p2 ==-1)//如果是数字,直接给P2
p2 = (int)(sz[i+1]);
dt[j+2] = p1 && p2;//与运算
sz[i-1] = j+2;
j++;
j2++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 < s-j1-2*j2; i1++)//将后续式子前移两项
sz[i1] = sz[i1+2];
i = i-1;
}
for(i = 0; i < s-j1-2*j2-2*j3; i++) // 处理或。
if(sz[i] == '|'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2=2;i2<j+2;i2++) {
if(sz[i-1] == i2)  //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2)//如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1)//如果是数字,直接给P1
p1 = sz[i-1];
if(p2 == -1)//如果是数字,直接给P2
p2 = sz[i+1];
dt[j+2] = p1 || p2;//或运算
sz[i-1] = j+2;
j++;
j3++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 < s-j1-2*j2-2*j3; i1++)//将后续式子前移两项
sz[i1]=sz[i1+2];
i--;
}
for(i = 0; i < s-j1-2*j2-2*j3-2*j4; i++) // 处理蕴含。
if(sz[i] == '^'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2 = 2; i2 < j+2; i2++) {
if(sz[i-1] == i2) //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2) //如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1)//如果是数字,直接给P1
p1 = sz[i-1];
if(p2 == -1)//如果是数字,直接给P2
p2 = sz[i+1];
dt[j+2] = (!p1) || p2;//蕴含运算
sz[i-1] = j+2;
j++;
j4++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 < s-j1-2*j2-2*j3-2*j4; i1++)//将后续式子前移两项
sz[i1] = sz[i1+2];
i--;
}
for(i = 0; i < s-j1-2*j2-2*j3-2*j4-2*j5; i++) // 处理等值。
if(sz[i] == '~'){
for(i1 = 0; i1 < h0; i1++){
if(sz[i-1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if(sz[i+1] == ccu[i1])//将变量赋值并给P2
p2 = icu[i1];
}
for(i2 = 2; i2 < j+2; i2++) {
if(sz[i-1] == i2) //如果为前计算结果,将结果赋值并给P1
p1 = dt[i2];
if(sz[i+1] == i2) //如果为前计算结果,将结果赋值并给P2
p2 = dt[i2];
}
if(sz[i-1] == -2)//如果是前运算结果的0,则P1等于0
p1 = 0;
if(sz[i+1] == -2)//如果是前运算结果的0,则P2等于0
p2 = 0;
if(p1 == -1)//如果是数字,直接给P1
p1 = sz[i-1];
if(p2 == -1)//如果是数字,直接给P2
p2 = sz[i+1];
dt[j+2] = (!p1 || p2) && (!p2 || p1);//等值运算
sz[i-1] = j+2;
j++;
j5++;
p1 = -1;
p2 = -1;
for(i1 = i; i1 < s-j1-2*j2-2*j3-2*j4-2*j5; i1++)//将后续式子前移两项
sz[i1] = sz[i1+2];
i--;
}
return dt[j+1];//返回结果
}
}

/**分级运算函数**/
int CR(char sz
,char ccu
,int icu
,int h0)
{
int i,j,h,s,kh = 0,wz
,a;
char xs1
,ckh
;			//xs1用来保存括号内的字符 ckh用来保存括号。
s = strlen(sz);
for(i = 0; i < s; i++)
if(sz[i] == '(' || sz[i] == ')'){	//判断括号
wz[kh] = i;					//存储括号位置
ckh[kh] = sz[i];			//存储括号类型
kh++;
}
if(kh == 0)
return MAP(sz,ccu,icu,h0);	//如果无括号,直接运行
else{
for(i = 0; i < kh; i++)
if(ckh[i] == ')')			//找到第一个" )"
break;
for(j = wz[i-1]+1,h=0; j < wz[i]; j++,h++) //存储最内级括号中的内容
xs1[h] = sz[j];
xs1[h] = '\0';
a = MAP(xs1,ccu,icu,h0);		//运行最内级括号的式子,得到结果
if(a == 1)					//判断并存储结果
sz[wz[i-1]] = 1;
else
sz[wz[i-1]] = -2;
for(j = wz[i-1]+1; j < s+wz[i-1] - wz[i]; j++)//将括号后内容前移
sz[j] = sz[j + wz[i] - wz[i-1]];
sz[j] = '\0';
return CR(sz,ccu,icu,h0);//循环执行
}
}

/**二进制赋值函数**/
void BVA(int b
,int f){
int i;
i = f;
if(b[f] == 0)	 //加1
b[f] = 1;
else			//进位
{
b[f] = 0;
BVA(b,--i);
}
}

/**求任意一个命题公式的真值表**/
void Matrice(){
int i2,d=1,icu
,kh=0,jg,j=0,h0;		//icu
用于存放变量值,kh括号计数,jg存放结果
int bj=0,x=0,xq
;				//hq
存放合取结果xq
存放析取结果
char sz
,ccu
,sz0
;					//sz
存放式子,ccu
存放变量,sz0
也是用于存放式子
hq[0]=-1;
xq[0]=-1;
printf("\n\t\t*************************************************\n");
printf("\t\t**                                             **\n");
printf("\t\t**       (可运算真值表,主范式,支持括号)      **\n");
printf("\t\t**                                             **\n");
printf("\t\t**                  用!表示非                  **\n");
printf("\t\t**                  用&表示与                  **\n");
printf("\t\t**                  用|表示或                  **\n");
printf("\t\t**                 用^表示蕴含                 **\n");
printf("\t\t**                 用~表示等值                 **\n");
printf("\t\t**                                             **\n");
printf("\t\t*************************************************\n");
sg:	printf("\t\t");
gets(sz);
strcpy(sz0,sz);
for(i1 = 0; (size_t)i1 < strlen(sz); i1++){
if(sz[i1] =='!' || sz[i1] == '&' || sz[i1] == '|' || sz[i1] == '^' || sz[i1] == '~' || sz[i1] == '(' || sz[i1] == ')' || sz[i1] >= 'a' && sz[i1] <= 'z' || sz[i1] >= 'A' && sz[i1] <= 'Z'){
if(sz[i1] == ')' || sz[i1] == '(')//存储括号数量
kh++;
if(sz[i1] >= 'a' && sz[i1] <= 'z' || sz[i1] >= 'A' && sz[i1] <= 'Z') {
if(sz[i1+1] >= 'a' && sz[i1+1] <= 'z' || sz[i1+1] >= 'A' && sz[i1+1] <= 'Z'){
printf("\t\t#          您输入的数据不合法!请重新输入!\n");
goto sg;
}
for(i2 = 0; i2 < j; i2++) //判断并储存变量。
if(ccu[i2] == sz[i1])//去除重复变量
d = 0;
if(d == 1){
ccu[j] = sz[i1];
j++;
}
d = 1;
}
}
else{
printf("\t\t#          您输入的数据不合法!请重新输入!\n");
goto sg;
}
}
printf("\n\t\t*************************************************\n");
printf("\n\t\t该命题公式中的变量个数为:%d\n",j);//输出变量个数
h0 = j;
printf("\n\t\t输出真值表如下:\n \n"); //输出真值表表头
printf("\t\t");
for(i1 = 0; i1 < h0; i1++)
printf(" %c ",ccu[i1]);
printf(" ");
printf("\t\t");
puts(sz);
printf("\n");
for(i1 = 0; i1 < j; i1++) ///////先将所有的变量赋值为零。
icu[i1] = 0;
printf("\t\t");
for(i2 = 0; i2 < j; i2++)//输出真值表前项
printf(" %d ",icu[i2]);
jg = CR(sz,ccu,icu,h0); //用函数求结果
if(jg == 0)
hq[h++] = bj;
printf("\t\t%d\n",jg);//输出运算结果
strcpy(sz,sz0);
for(i1 = 0; i1 < (int)pow(2,j)-1; i1++){
++bj;
BVA(icu,j-1); //赋值变量
jg = CR(sz,ccu,icu,h0);
if(jg == 0)
hq[h++] = bj;
strcpy(sz,sz0); //恢复被修改的数组。
printf("\t\t");
for(i2 = 0; i2 < j; i2++)
printf(" %d ",icu[i2]);//输出真值表前项
printf("\t\t%d\n",jg);//输出运算结果
}
printf("\n");
}

void Ma_Start(){
int hq1
,hq2
,j = 0,flag = 0;
printf("\n\t\t*************************************************\n");
printf("\t\t**                                             **\n");
printf("\t\t#            输入合法的逻辑表达式P              #");
getchar();
Matrice();
for(i1 = 0; i1 < h; i1++){
hq1[j] = hq[i1];
}
printf("\t\t#            输入合法的逻辑表达式Q              #");
Matrice();
for(i1 = 0; i1 < h; i1++){
hq2[j] = hq[i1];
}
for(i1 = 0; i1 < h; i1++){//判断两个逻辑表达式是否等价
if(hq1[i1] != hq2[i1]){
flag = 0;
break;
}
else
flag = 1;
}
if(flag == 0)printf("\t\t#          您输入的两个逻辑表达式不等价         #\n");
else if(flag == 1)printf("\t\t#           您输入的两个逻辑表达式等价          #\n");
printf("\t\t**                                             **\n");
printf("\t\t*************************************************\n");
printf("\t\t");
}

void Start(){
char s;
printf("\t\t*************************************************\n");
printf("\t\t**                                             **\n");
printf("\t\t**              欢迎使用逻辑运算器             **\n");
printf("\t\t**                                             **\n");
printf("\t\t*************************************************\n");
navi : printf("\n\t\t*************************************************\n");
printf("\t\t**                                             **\n");
printf("\t\t**         您可以选择a或b执行以下操作          **\n");
printf("\t\t**     a、测试P,Q两个逻辑表达式是否逻辑等价    **\n");
printf("\t\t**               b、退出系统                   **\n");
printf("\t\t**                                             **\n");
printf("\t\t*************************************************\n");
printf("\t\t");
scanf("%c",&s);
switch(s){
case 'a' : system("cls");Ma_Start();break;
case 'b' : break;
default : printf("\t\tenter data error!\n");
}
if(s != 'b')
goto navi;
else{             //退出
printf("\t\t*************************************************\n");
printf("\t\t**                                             **\n");
printf("\t\t**              欢迎再次使用!谢谢!           **\n");
printf("\t\t**                                             **\n");
printf("\t\t*************************************************\n");
}
}

int main(){
Start();
return 0;
}


总结:求任意一个命题公式的真值表及其主范式就相对较难,解决了求命题公式的真值表及其主范式的问题后,求两逻辑表达式是否等价就变得十分简单,关键在与求一个命题公式的真值表。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言
相关文章推荐