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

来源:互联网 发布:中国移动网络加速器 编辑:程序博客网 时间:2024/06/07 06:24

一、程序通过编译,并实现两个命题的各种逻辑运算

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

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

一、算法分析

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

C语言算法:

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

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

②    

/**主运算函数**/intMAP(char sz[N],char ccu[N],int icu[N],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[N];  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[N],char ccu[N],int icu[N],int h0){        int i,j,h,s,kh = 0,wz[N],a;        char xs1[N],ckh[N];                 //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[N],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[N],i1,h=0;//定义全局变量/**主运算函数**/int MAP(char sz[N],char ccu[N],int icu[N],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[N];  s = strlen(sz);  if(s == 1)if(sz[0] == -2)//判断是否是最后一项return 0;elsereturn 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])//将变量赋值并给P1p1 = icu[i1];if(sz[i+1] == -2)//如果是前运算结果的0,则P1等于0p1 = 0; if(p1 == -1)//如果是数字,直接给P1p1 = 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])//将变量赋值并给P1p1 = icu[i1];if(sz[i+1] == ccu[i1])//将变量赋值并给P2p2 = 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[N],char ccu[N],int icu[N],int h0){  int i,j,h,s,kh = 0,wz[N],a;   char xs1[N],ckh[N];//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[N],int f){  int i;  i = f;  if(b[f] == 0) //加1b[f] = 1;  else//进位  {b[f] = 0;BVA(b,--i);  } }/**求任意一个命题公式的真值表**/void Matrice(){int i2,d=1,icu[N],kh=0,jg,j=0,h0;//icu[N]用于存放变量值,kh括号计数,jg存放结果int bj=0,x=0,xq[N];//hq[N]存放合取结果xq[N]存放析取结果char sz[N],ccu[N],sz0[N];//sz[N]存放式子,ccu[N]存放变量,sz0[N]也是用于存放式子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[N],hq2[N],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;}

总结:求任意一个命题公式的真值表及其主范式就相对较难,解决了求命题公式的真值表及其主范式的问题后,求两逻辑表达式是否等价就变得十分简单,关键在与求一个命题公式的真值表。




1 0
原创粉丝点击