一. 题目分析
题目要求为:模拟图灵机的运行过程,在本题中,模拟了图灵机的XN*2的过程,要求输出每一个指令步骤的结果。通过对图灵机运行过程的模拟,对于其中的原理理解更为深刻。
对于处理之后得到的字符串,初始化内态为零,进行单个字符的读入,对于每个字符,进行内态与输入字符的判断,对于不同的情况,得到不同的内态和相应的输入改变(可能改变,也可能不变),重复这个过程,直到进行到终止的命令。再将得到的终止命令进行相应的转化处理,得到相应的结果并输出。
二.算法构造
大致思路:
1.一开始将输入的数字转换为二进制数据,再将二进制数转换为图灵机对应的磁带编码,
2.对这个得到的编码,使用图灵机的指令集进行编码,在编码过程中,对于每一种指令的执行之后,输出相应的执行指令,内态以及相应的输入字符的改变情况,再递归,继续下一步的指令操作。
3.编码之后,将得到的编码进行还原,即将相应的编码先转化为二进制,再将二进制转换为相应的数字,输出,得到结果。
三. 算法实现
//模拟图灵机XN*2
//auhtor:lyq
// time:2019-3-17
#include<iostream>
#include<string>
#include<stdlib.h>
#include<cmath>
using namespace std;
string c;//全局变量--输入的原始数据对应的字符串
int i=0;//全局变量--字符串计数变量
string f(int a,char c1)//处理函数
{
int n=c.length();//输如字符串的长度
if(a== 0)
{
if(c1=='0')
{
cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"0"<<" "<<"0 R"<<endl;
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
cout<<"下一个内态为:"<<"0"<<"当前输入不变"<<endl;
if(i+1== n)//自动补零
c+='0';
a=0;
cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
cout<<endl;
return (f(a,c[++i]));
}
else if(c1=='1')
{
cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"1"<<" "<<"0 R"<<endl;
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
cout<<"下一个内态为:"<<"1"<<"当前输入更改为:0"<<endl;
if(i+1== n)//自动补零
c+='0';
a=1;
c[i]='0';
cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
cout<<endl;
return (f(a,c[++i]));
}
else
{
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
//cout<<"输入的字符串错误!"<<endl;//异常输入的处理
return " ";
}
}
else if(a== 1)
{
if(c1=='0')
{
cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"0"<<" "<<"1 R"<<endl;
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
cout<<"下一个内态为:"<<"0"<<"当前输入更改为:1"<<endl;
if(i+1== n)//自动补零
c+='0';
a=0;
c[i]='1';
cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
cout<<endl;
return(f(a,c[++i]));
}
else if(c1=='1')
{
cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"10"<<" "<<"0 R"<<endl;
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
cout<<"下一个内态为:"<<"10"<<"当前输入更改为:0"<<endl;
if(i+1== n)//自动补零
c+='0';
a=10;
c[i]='0';
cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
cout<<endl;
return (f(a,c[++i]));
}
else
{
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
//cout<<"输入字符串错误"<<endl;
return " ";
}
}
else if(a== 10)
{
if(c1=='0')
{
cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"11"<<" "<<"1 R"<<endl;
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
cout<<"下一个内态为:"<<"11"<<"当前输入更改为:1"<<endl;
if(i+1== n)//自动补零
c+='0';
a=11;
c[i]='1';
cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
cout<<endl;
return (f(a,c[++i]));
}
else
{
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
//cout<<"字符串错误!"<<endl;
return " ";
}
}
else if(a== 11)
{
if(c1=='0')
{
cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"0"<<" "<<"1 STOP"<<endl;
cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
if(i+1==n)//自动补零
c+='0';
a=0;
c[i]='1';
cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
cout<<endl;
return c;
}
else
{
cout<<"当前内态为:"<<a<<";当前输入为:"<<c1<<endl;
//cout<<"字符串错误!"<<endl;
return " ";
}
}
}
string turn_to(string c)//转换二进制数为磁带上的编码
{
string a;
a+='0';
for(int i=0;i<c.length();i++)
{
if(c[i] == '0')
a+= '0';
else if(c[i] =='1')//1转换为10
{
a+='1';
a+='0';
}
else if(c[i]=',')//"," 转化为110
{
a+='1';
a+='1';
a+='0';
}
}
return a;
}
string turn(string c)//转换为二进制
{
string b;
int i=0;
while(i<c.length())//找到第一个1
{
if(c[i]=='1')
break;
i++;
}
int t=i;
while(t<c.length())
{
if(c[t]=='0')//遇到零
{
t++;
b+='0';
}
else//当前指向为1
{
if(c[t+1]=='0')//遇到10两个字符
{
t+=2;//后移两个位置
b+='1';
}
else if(c[t+1]=='1')//遇到11两个字符,转换为,结束
return b;
}
}
}
int to(string c)//二进制转换为十进制
{
int n=0,m=0;
int t=0;
int a=c.length()-1;
while(a>=0)
{
n=c[a]-'0';//转化为对应的数字
m+=n*pow(2,t);
t++;
a--;
}
return m;
}
int isnum(string c)//判断是否为数字对应的字符串
{
float b=atof(c.c_str());//将输入的字符串转换为数字
if(b<=0||(b!=(int)b))//进行输入的数的异常处理
{
cout<<"输入的数"<<"不是一个正整数!"<<endl;
cout<<endl;
return 0;
}
else
return 1;//返回1带代表输入的数正确
}
int main(void)
{
string x;
int t;
int r;
string w;
char p[100];//用于存储进制转换后对应的字符
string m;
cout<<"请输入要进行操作的数:"<<endl;
cin>>x;
if(isnum(x))
{
cout<<"输入错误!"<<endl;
return 1;
}
else
{
t=atoi(x.c_str());
itoa(t,p,2);//十进制转换为二进制
m=p;
m+=',';//末尾自动加,表示结束
cout<<"此数对应的二进位记号为:0"<<m;
cout<<endl;
c=turn_to(m);//转换为对应的磁带编码
cout<<"此数对应的磁带编码为:"<<c<<endl;
cout<<endl;
int a=0;//内态初始值为0;
string b=f(a,c[0]);//得到转换之后的编码
w=turn(b);//将此编码转换为二进制
cout<<"最终结果对应的磁带编码为:"<<b<<endl;
cout<<"最终结果对应的二进制位:"<<w<<endl;
r=to(w); //将二进制转换为对应的整数
cout<<"最终结果为:"<<r<<endl;
return 0;
}
}
四. 调试与测试截图
(1)调试截图:
输入:
转换成二进位符号:
转换成磁带编码:
指令操作之后得到的结果对应的二进制:
得到的最后结果:
(2).测试截图:
错误输入测试:
测试数据3:
输入数据:12
五.经验归纳
图灵机的运行过程与两个重要的参数有关,一个是当前图灵机的内态,一个是当前的输入,对于不同的情况,有不同的指令操作。
在这次的实验中,将所有情况罗列出来,运行一条指令之后赋予相关的新的内态,以及新的输入,进行递归调用,进行下一个指令的操作,直到遇见停止的指令。
遇到的问题,在实现过程中,对于相应的转换函数,比如二进制到十进制的相互转换,此类函数运用的不是很熟练,出现了一些小错误,考虑到可以自己写进制转换的函数,于是在转换为二进制时自己写了一个进制转换函数。