利用真值表法求取主析取范式以及主合取范式的实现

利用真值表法求取主析取范式以及主合取范式的实现
利用真值表法求取主析取范式以及主合取范式的实现

#include

#include

#include

#include

using namespace std;

char str[100]; //输入的命题公式

int tv[20] = {0}; //真值指派的数组

int length; //命题公式长度

char expression[100]; //将命题公式中的命题变元变为真值后的数组

int icp(const char c) //联结词的栈外优先级

{

int result = -1;

switch(c)

{

case '#': result = 0; break;

case '(': result = 10; break;

case '!': result = 9; break;

case '&': result = 6; break;

case '|': result = 4; break;

case '>': result = 2; break;

case ')': result = 1;

}

return result;

}

int isp(const char c) //联结词的栈内优先级

{

int result = -1;

switch(c)

{

case '#': result = 0; break;

case '(': result = 1; break;

case '!': result = 8; break;

case '&': result = 7; break;

case '|': result = 5; break;

case '>': result = 3; break;

case ')': result = 10;

}

return result;

}

void Plus(int a[],int q) //二进制加法指派真值

{

a[q]=a[q]+1;

for (int i = q; a[i] == 2; i--)

{

a[i]=0;

a[i-1]=a[i-1]+1;

}

}

template

class Stack

{

public:

virtual bool IsEmpty() const = 0;

virtual bool IsFull() const = 0;

virtual bool Top(T& x) const = 0;

virtual bool Push(T x) = 0;

virtual bool Pop() = 0;

virtual void Clear() = 0;

};

template

class SeqStack: public Stack //顺序栈类

{

public:

SeqStack(int mSize = 30);

~SeqStack() { delete []s; }

bool IsEmpty() const { return top == -1; }

bool IsFull() const { return top == maxTop; } bool Top(T& x) const;

bool Push(T x);

bool Pop();

void Clear() { top = -1; }

private:

int top;

int maxTop;

T* s;

};

template

SeqStack::SeqStack(int mSize)

{

maxTop = mSize - 1;

s = new T[mSize];

top = -1;

}

template

bool SeqStack::Top(T& x) const

{

if (IsEmpty())

{

cout << "Empty" << endl;

return false;

}

x = s[top];

return true;

}

template

bool SeqStack::Push(T x)

{

if (IsFull())

{

cout << "Overflow" << endl;

return false;

}

s[++top]=x;

return true;

}

template

bool SeqStack::Pop()

{

if(IsEmpty())

{

cout << "Underflow" << endl;

}

top--;

return true;

}

class Calculator

{

public:

Calculator(int maxSize):s(maxSize){}

void Change();

int Run();

void Solve();

void Clear() { s.Clear(); }

private:

SeqStack s; //运算栈

void PushOperand(bool);

bool GetOperands(bool &, bool &);

void DoOperator(char);

};

void Calculator::PushOperand(bool op)

{

s.Push(op);

}

bool Calculator::GetOperands(bool & op1, bool & op2) //获取栈顶两个元素{

if (!s.Top(op1))

{

cerr << "Missing operand!" << endl;

return false;

}

s.Pop();

if (!s.Top(op2))

{

cerr << "Missing operand!" << endl;

return false;

}

s.Pop();

return true;

}

void Calculator::DoOperator(char oper) //联结词运算

{

bool left, right;

bool result = GetOperands(left, right);

if (result)

switch(oper)

{

case '!': s.Push(!left && right); break; //not运算

case '&': s.Push(left && right); break; //and运算

case '|': s.Push(left || right); break; //or运算

case '>': s.Push(!right || left); break; //条件运算

}

else

Clear();

}

void Calculator::Change() //将输入的字符串转化为可计算的表达式

{

int k = 0, t = 0;

int flag = 1; //标记,防止相同的命题变元赋入不同的值

int count = 0;

for (int i = 0; i < pow(2,count); i++)

{

k=1;

for (int m = 0; m < length; m++)

{

if (isalpha(str[m])) //将原来的命题变元修改为真值

{

if (flag == 1)

{

if(tv[k] == 0)

expression[m] = '0';

else

expression[m] = '1';

k++;

}

else

expression[m] = '0';

flag = 1;

for (t = m; t >= 0; t--)

if ((str[m+1] == str[t]) && isalpha(str[m+1]) && isalpha(str[t]))

flag = 0;

}

else

{

expression[m] = str[m]; //逻辑联结词不变

for (t = m; t >= 0; t--)

if ((str[m+1] == str[t]) && isalpha(str[m+1]) && isalpha(str[t]))

flag = 0;

}

}

for (int t = 0; t < length; t++)

for (int j = t; j < length; j++)

if (str[t] == str[j])

expression[j] = expression[t]; //相同的命题变元复制赋值}

}

int Calculator::Run()

{

SeqStack s1; //联结词栈

char ch, y;

char p[100];

int i = 0;

s1.Push('#');

for (int temp=0; temp < length ; temp++)

{

ch = expression[temp];

if (isdigit(ch))

{

p[i++] = ch;

}

else if(ch == ')')

for(s1.Top(y), s1.Pop(); y != '('; s1.Top(y), s1.Pop())

p[i++] = y;

else

{

if(ch == '!') p[i++] = '1'; //非运算,在!前加1,将!视作双目操作符

for(s1.Top(y), s1.Pop(); icp(ch) <= isp(y); s1.Top(y), s1.Pop())

p[i++] = y;

s1.Push(y);

s1.Push(ch);

}

}

while(!s1.IsEmpty())

{

s1.Top(y);

s1.Pop();

if(y != '#')

p[i++] = y;

}

p[i++] = '#';

/* ------↑中缀表达式转化为后缀表达式-----

------↓计算后缀表达式结果------------- */

bool newop;

for (i = 0; p[i] !='#'; i++)

{

switch(p[i])

{

case '!':

case '&':

case '|':

case '>': DoOperator(p[i]); break;

default:

cin.putback(p[i]);

cin >> newop;

PushOperand(newop);

break;

}

}

if (s.Top(newop))

{

cout << (int)newop << endl;

return (int)newop; //输出并返回最终结果

}

}

void Calculator::Solve()

{

cout << "***************************************" << endl;//标语cout << "** 欢迎进入逻辑运算软件**" << endl;

cout << "** (可运算真值表,主范式,支持括号) **" << endl;

cout << "** **" << endl;

cout << "** 用!表示not 用&表示and **" << endl;

cout << "** 用|表示or 用>表示蕴含**" << endl;

cout << "** **" << endl;

cout << "***************************************" << endl;

cout << "请输入合法的命题公式(以#结尾): ";

int flag = 1; //标记,防止重复添加命题变元

int count = 0; //命题变元的数目

cin >> str; //输入命题公式

length = strlen(str) - 1;

char index[10]; //命题变元数组

for (int i = 0; i < length; i++) //逐次添加命题变元

{

if (isalpha(str[i]) && (flag == 1))

index[count++] = str[i];

flag=1;

for (int k = 0; k < count; k++)

if (index[k] == str[i+1])

flag=0;

}

if (!count)

{

cout << "无命题变元,重新输入!" << endl;

system("pause");

system("cls");

Solve();

}

cout << "真值表:" << endl;

for (int w = 0; w < count; w++)

cout << index[w] << ' ';

for (w = 0; w < length; w++)

cout << str[w];

cout << endl;

int *truth = new int[pow(2,count)];

int xx = 0, dx = 0; //小项,大项

for (int r = 0; r < pow(2,count); r++) //输出真值表{

for (int j = 1; j <= count; j++)

cout << tv[j] << ' ';

Change();

truth[r] = Run();

if (truth[r]) //记录小项和大项的个数

xx++;

else

dx++;

Plus(tv,count);

}

if(xx > 1) //输出主析取范式

{

int flag_xx = 0;

cout << "主析取范式为";

for(r = 0; r < pow(2,count); r++)

{

if (truth[r])

{

if (flag_xx) cout << " \\/ ";

cout << "m" << r;

flag_xx = 1;

}

}

cout << endl;

}

else

cout << "没有主析取范式!" << endl;

if(dx > 1) //输出主合取范式

{

int flag_dx = 0;

cout << "主合取范式为";

for(r = 0; r < pow(2,count); r++)

{

if (!truth[r])

{

if (flag_dx) cout << " /\\ ";

cout << "M" << r;

flag_dx = 1;

}

}

cout << endl;

}

else

cout << "没有主合取范式!" << endl;

cout << "是否继续运算?(Y/N)" << endl;

char goon;

cin >> goon;

if (goon=='y' || goon=='Y')

{

system("cls");

Solve(); //递归调用Solve,重新计算}

else

exit(0);

}

int main()

{

Calculator Cal(100);

Cal.Solve();

return 0;

}

利用真值表法求取主析取范式以及主合取范式的实现-副本

#include "" #include "" #include "" #include "" #define N 50 void pd(int b[N],int f); int H1 (char T1[N], char T2[N], int T3[N], int y); int H2 (char T1[N], char T2[N], int T3[N], int y); int main() { int i1,i2,d=1,T3[N],kh=0,jg,j=0,y; int w=0,hequ[N],h=0,x=0,xiqu[N]; char T1[N],T2[N],T10[N],s; hequ[0]=-1; xiqu[0]=-1; printf("#########################################\n"); printf("## 用!表示否定 ##\n"); printf("## 用&表示合取 ##\n"); printf("## 用|表示析取 ##\n"); printf("## 用^表示条件 ##\n"); printf("## 用~表示双条件 ##\n"); printf("#########################################\n\n"); printf("请输入一个合法的命题公式:\n"); gets(T1); strcpy(T10,T1); for(i1=0;i1='a' && T1[i1]<='z' || T1[i1]>='A' && T1[i1]<='Z') { for(i2=0;i2

主范式的求法及应用

分类号O158 单位代码 11395 密级学号 1204210135 学生毕业论文 题目主范式的求法及应用 作者王定超 院 (系) 数学与统计学院 专业数学与应用数学 指导教师祁兰 答辩日期 2016年5月21日

榆林学院 毕业论文诚信责任书 本人郑重声明:所呈交的毕业论文,是本人在导师的指导下独立进行研究所取得的成果。毕业论文中凡引用他人已经发表或未发表的成果、数据、观点等,均已明确注明出处。尽我所知,除文中已经注明引用的内容外,本论文不包含任何其他个人或集体已经公开发表或撰写过的研究成果.对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明. 本人毕业论文与资料若有不实,愿意承担一切相关的法律责任。 论文作者签名: 年月日

摘要 主范式即主合取范式与主析取范式,它是数理逻辑中重要的基石也是推动计算机科学发展的动力,其方法与应用颇有价值.本文通过介绍主范式的相关定理、定义并作出相应解释,以及由范式的不唯一性引出主范式的唯一性,得到求主范式的三种方法:真值表法、真值指派法、等值演算法,并给出主范式的四种应用:判断几个命题公式是否等价、命题公式的类型、求公式的成真成假赋、解决实际问题. 关键词:主范式;真值表;真值指派法;等值演算法

ABSTRACT The method and application of p rincipal normal form ABSTRACT Principal normal form are the host conjunctive normal form and the host disjunctive normal form. It is an important cornerstone in the mathematical logic and the power of impelling the computer science development. The method and the application is of great value. In this paper, we make corresponding explanation and the non-uniqueness of the paradigm leads to the uniqueness of principal normal form by the introduction of related theorem of principal normal form and definition. We get the methods of principal normal form: truth table method, true value assignment method, and equivalent calculating method, and then give the applications of principal normal form: judging several propositional formulas whether equivalent or not, the type of propositional formula, seeking the formula of becoming true or false, and solve practical problems. Keywords:principal normal form; truth table; true value assignment method; equivalent calculating method

计算机自动求解命题公式的主范式

3 计算机自动求解命题公式的主范式 一.需求分析 (1)用户输入一任意命题公式,计算机程序自动输出其主析取范式和主合取范式。(2)求任意一个命题公式的真值表,并根据真值表求主范式。 (3)关于命题公式的形式和运算符(即联结词)的运算 首先根据离散数学的相关知识,命题公式由命题变元和运算符(即联结词)组成,命题变元用大写字母英文表示(本次试验没有定义命题常元T和F,即T、F都表示命题变元),每个命题变元都有两种真值指派0和1,对应于一种真值指派,命题公式有一个真值,由所有可能的指派和命题公式相应的真值按照一定的规范构成的表格称为真值表。 目前离散数学里用到的包括扩充联结词总共有九种,即析取(或)、合取(与)、非、蕴含、等值、与非、或非、异或、蕴含否定,常用的为前五种,其中除了非运算为一元运算以外,其它四种为二元运算。所以本次实验设计时只定义了前五种运算符,同时用“/”表示非,用“*”表示合取,用“+”表示析取,用“>”表示蕴含,用“:”表示等值,且这五种运算符的优先级依次降低,如果需用括号改变运算优先级,则用小括号()改变。 以下为上述五种运算符运算时的一般真值表,用P和Q表示命题变元: 1.非,用“/”表示 P /P 0 1 1 0 2. 合取(与),用“*”表示 P Q P*Q 0 0 0 0 1 0 1 0 0

1 1 1 3.析取(或),用“+”表示 P Q P+Q 0 0 0 0 1 1 1 0 1 1 1 1 4.蕴含,用“>”表示 P Q P>Q 0 0 1 0 1 1 1 0 0 1 1 1 5.等值,用“:”表示 P Q P:Q 0 0 1 0 1 0 1 0 0 1 1 1 下面是求取后缀表达式的规则: 1.从中缀表达式左边起逐个字符判断,如果是命题变元,则直接输出;如果是运算符,则将其与当前有效栈顶字符(即非空,可能为运算符或左半括号;如果栈为空,则直接入栈)的优先级比较,如果大于栈顶字符优先级,则直接入栈,如果小于或等于栈顶字符优先级,则弹出栈中字符并输出,直到大于栈顶字符优先级; 2.如果遇到左半括号,则直接入栈,也就是栈外左半括号的优先级最高,入栈以后,其优先级变为最低,也就是不管下一个字符是什么,该左半括号都不出栈,当且仅当遇到与其对应的右半括号时(遇到右半括号前,所有的字符按1中的规则或左半括号的入栈规则入栈或出栈),将栈中该左半括号以上的字符按

利用真值表法求取主析取范式以及主合取范式的实现

#include #include #include #include using namespace std; char str[100]; //输入的命题公式 int tv[20] = {0}; //真值指派的数组 int length; //命题公式长度 char expression[100]; //将命题公式中的命题变元变为真值后的数组 int icp(const char c) //联结词的栈外优先级 { int result = -1; switch(c) { case '#': result = 0; break; case '(': result = 10; break; case '!': result = 9; break; case '&': result = 6; break; case '|': result = 4; break; case '>': result = 2; break; case ')': result = 1; } return result; } int isp(const char c) //联结词的栈内优先级 { int result = -1; switch(c) { case '#': result = 0; break; case '(': result = 1; break; case '!': result = 8; break; case '&': result = 7; break; case '|': result = 5; break; case '>': result = 3; break; case ')': result = 10; } return result; } void Plus(int a[],int q) //二进制加法指派真值

利用真值表法求取主析取范式以及主合取范式的实现

#include "stdio.h" #include "stdlib.h" #include "string.h" #include "math.h" #define N 50 void pd(int b[N],int f); int H1 (char T1[N], char T2[N], int T3[N], int y); int H2 (char T1[N], char T2[N], int T3[N], int y); int main() { int i1,i2,d=1,T3[N],kh=0,jg,j=0,y; int w=0,hequ[N],h=0,x=0,xiqu[N]; char T1[N],T2[N],T10[N],s; hequ[0]=-1; xiqu[0]=-1; printf("#########################################\n"); printf("## 用!表示否定 ##\n"); printf("## 用&表示合取 ##\n"); printf("## 用|表示析取 ##\n"); printf("## 用^表示条件 ##\n"); printf("## 用~表示双条件 ##\n"); printf("#########################################\n\n"); printf("请输入一个合法的命题公式:\n"); gets(T1);

strcpy(T10,T1); for(i1=0;i1='a' && T1[i1]<='z' || T1[i1]>='A' && T1[i1]<='Z') { for(i2=0;i2

主范式的求法及应用

分类号O158 单位代码11395 密级学号1204210135 学生毕业论文 题目主式的求法及应用 作者王定超 院(系) 数学与统计学院 专业数学与应用数学 指导教师祁兰 答辩日期2016年5月21日

榆林学院 毕业论文诚信责任书 本人重声明:所呈交的毕业论文,是本人在导师的指导下独立进行研究所取得的成果。毕业论文中凡引用他人已经发表或未发表的成果、数据、观点等,均已明确注明出处。尽我所知,除文中已经注明引用的容外,本论文不包含任何其他个人或集体已经公开发表或撰写过的研究成果.对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明. 本人毕业论文与资料若有不实,愿意承担一切相关的法律责任。 论文作者签名: 年月日

摘要 主式即主合取式与主析取式,它是数理逻辑中重要的基石也是推动计算机科学发展的动力,其方法与应用颇有价值.本文通过介绍主式的相关定理、定义并作出相应解释,以及由式的不唯一性引出主式的唯一性,得到求主式的三种方法:真值表法、真值指派法、等值演算法,并给出主式的四种应用:判断几个命题公式是否等价、命题公式的类型、求公式的成真成假赋、解决实际问题. 关键词:主式;真值表;真值指派法;等值演算法

The method and application of p rincipal normal form ABSTRACT Principal normal form are the host conjunctive normal form and the host disjunctive normal form. It is an important cornerstone in the mathematical logic and the power of impelling the computer science development. The method and the application is of great value. In this paper, we make corresponding explanation and the non-uniqueness of the paradigm leads to the uniqueness of principal normal form by the introduction of related theorem of principal normal form and definition. We get the methods of principal normal form: truth table method, true value assignment method, and equivalent calculating method, and then give the applications of principal normal form: judging several propositional formulas whether equivalent or not, the type of propositional formula, seeking the formula of becoming true or false, and solve practical problems. Keywords:principal normal form; truth table; true value assignment method; equivalent calculating method

利用真值表法求取主析取范式以及主合取范式的实现---副本

利用真值表法求取主析取范式以及主合取范式的实现---副本

#include "stdio.h" #include "stdlib.h" #include "string.h" #include "math.h" #define N 50 void pd(int b[N],int f); int H1 (char T1[N], char T2[N], int T3[N], int y); int H2 (char T1[N], char T2[N], int T3[N], int y); int main() { int i1,i2,d=1,T3[N],kh=0,jg,j=0,y; int w=0,hequ[N],h=0,x=0,xiqu[N]; char T1[N],T2[N],T10[N],s; hequ[0]=-1; xiqu[0]=-1; printf("####################################### ##\n"); printf("## 用!表示否定##\n"); printf("## 用&表示合取##\n");

printf("## 用|表示析取##\n"); printf("## 用^表示条件##\n"); printf("## 用~表示双条件##\n"); printf("####################################### ##\n\n"); printf("请输入一个合法的命题公式:\n"); gets(T1); strcpy(T10,T1); for(i1=0;i1='a' && T1[i1]<='z' || T1[i1]>='A' && T1[i1]<='Z') { for(i2=0;i2

命题公式主范式的求法及应用

PINGDINGSH AN UNIVERSITY 毕业论文(设计) 题目: 命题公式主范式的求法及应用 院(系):数学与信息科学学院 专业年级:数学与应用数学05级 姓名:马蓓蓓 学号:051030233 指导教师:屈聪硕士 2009月3日

PINGDINGSH AN UNIVERSITY Thesis (design) Subject: The Solution an d Ap plication o f Prin cipa l Norm For m co l l eg e:M a t h e ma t i c s a n d I n f o r ma t i o n S c i e n c e Ma j o r a n d G ra d e: M a t h e ma t i c s a n d A p p l i e d M a t h ema t i c s,G r a d e2005 Na me:M a B e i-b e i No.:051030233 Ad v i s o r:M a s t e r Q u-C o n g March3, 2009

中文摘要 本文介绍了命题公式主范式的基本定义及相关定理,并对其作出相应解释;在此基础上,探讨了命题公式主范式的两种求法--真值表和等值演算并举出相应的例子.最后,具体给出了主范式的七个方面的应用,并联系实际对这些应用加以阐述. 关键词:主范式,真值表,主析取范式,主合取范式 Abstract T h i s p a p e r i n t r o d u c e s t h e b a s i c d e f i n i t i o n s a n d r e l a t e d t h e o r e m s o f t h e p r i n c i p a l n o r m f o r m,w h i c h a r e e x p l a i n e d i n s o m e a s p e c t.O n t h e b a s e o f t h e s e,i n o r d e r t o s o l o v e t h e p r i n c i p a l n o r m f o r m,w e d i s c u s s t w o m e t h o d s w h i c h i s t r u t h t a b l e a n d e q u i v a l e n t c a l c u l u s,a n d c o m p a n y w i t h e x a m p l e s t o i l l u s t r a t e i t;f i n a l l y,t h e a p p l i c a t i o n o f t h e p r i n c i p a l n o r m f o r m i s g i v e n i n s e v e n a s p e c t s,w h i c h i s c o m b i n e d w i t h r e a l l i f e,a n d p o i n t o u t t h e a p p l i c a t i o n b y u n i o n a c t u a l e x a m p l e s. K e y w o r d s:P r i n c i p a l n o r m f o r m,T r u t h t a b l e,P r i n c i p a l d i s j u n c t i v e n o r m f o r m,P r i n c i p a l c o n j u n c t i v e n o r m f o r m

离散数学主析取范式主合取范式

实验二 实验题目: 生成主析取范式和主合取范式 实验目的: 1.熟悉地掌握计算机科学技术常用的离散数学中的概念、性质和运算;通过实验提高学生编写实验报告、总结实验结果的能力;使学生具备程序设计的思想,能够独立完成简单的算法设计和分析。 2.掌握命题逻辑中的联接词、真值表、主范式等,进一步能用它们来解决实际问题。 实验内容: 利用计算机构造真值表来建立主析取范式和主合取范式 实验原理: 1.合取:二元命题联结词。将两个命题P、Q联结起来,构成一个新的命题P ∧Q。这个新命题的真值与构成它的命题P、Q的真值间的关系为只有当两个命题变项P 为真, Q为真时方可P∧Q为真, 而P、Q只要有一为假则P∧Q 为假。 2.析取:二元命题联结词。将两个命题P、Q联结起来,构成一个新的命题P ∨Q。这个新命题的真值与构成它的命题P、Q的真值间的关系为只有当两个命题变项P为假, Q为假时方可P∨Q为假, 而P、Q只要有一为真则P∨Q为真。 3.真值表:表征逻辑事件输入和输出之间全部可能状态的表格。列出命题公式真假值的表。通常以1表示真,0 表示假。命题公式的取值由组成命题公式的命题变元的取值和命题联结词决定,命题联结词的真值表给出了真假值的算法。真值表是在逻辑中使用的一类数学表,用来确定一个表达式是否为真或有效。 4.主析取范式:在含有n个命题变元的简单合取式中,若每个命题变元与其否定不同时存在,而两者之一出现一次且仅出现一次,称该简单合取式为小项。由若干个不同的小项组成的析取式称为主析取范式;与A等价的主析取范式称为A的主析取范式。任意含n个命题变元的非永假命题公式A都存在与其等价的主析取范式,并且是惟一的。 5.主合取范式:在含有n个命题变元的简单析取式中,若每个命题变元与其否定不同时存在,而两者之一出现一次且仅出现一次,称该简单析取式为大项。由若干个不同的大项组成的合取式称为主合取范式;与A等价的主合取范式称为A 的主合取范式。任意含n个命题变元的非永真命题公式A都存在与其等价的主合取范式,并且是惟一的。

相关文档
最新文档