一、实验目的
1.掌握图灵机的概念和基本结构,理解图灵机的基本指令和编码方式;
2.掌握图灵机的编程方法。
二、实验内容
对于任意给定的一台Turing机和任意给定的字符串w(w不含空格),编程模拟此Turing机的运行过程,要求输出从开始运行起的每一步骤的结果。
三、要求
1.题目分析
选定一台图灵机(XN×2),输入一位十进制数,将该数据转化为二进制,然后将该二进制数据扩展,在扩展的二进位上实现该图灵机的运算指令,指令如下:
00→00R,
01→10R,
10→01R,
11→100R,
100→111R,
110→01STOP。
输出的结果为扩展后的二进制,需缩进为二进制,最后转化为十进制输出。
2.算法构造
①定义一个结构体,在结构体中定义一个数组data[N]和数组长度length,结构体变量为Data;
②在主函数中分别定义存储二进制数组、XN×2数组和用来存放内态和输入值的数组;
③编写十进制转化为二进制的代码,并将结果存放在数组A[]中;
④扩展二进制:在循环语句中用if语句判断数组A中的值是否等于1:
若是则执行命令B.data[B.length++]=0;B.data[B.length++]=1;
若否则执行B.data[B.length++]=0;最后将逗号的编码加在扩展二进制的后面;
⑤执行图灵机指令:给内态一个初始值0,判断内态、输入值与0、1的关系,逐步执行图灵机命令;
⑥缩进二进制并转化十进制:输出的结果为扩展二进制,因此需缩进二进制,并将二进制转化为十进制。
3.算法实现
#include<stdio.h>
#include<math.h>
#define N 100
typedef struct {
int data[N];
int length; //数组长度
}Data;
int main()
{
Data A,B; //A为二进制数组,B为XN×2数组
int y=0,i=0,x,c[2];//矩形,存放内态和输入的值
int sum=0;
A.length=0;
B.length=0;
printf("请输入一个数据\n");
scanf("%d",&x);
while(x!=0){
y=x%2;
B.data[i]=y;
i++;
x=x/2;
B.length++;
}
i--;
printf("二进制为:");
for(;i>=0;--i){
A.data[A.length++]=B.data[i];
}
//输出二进制数
for(i=0;i<A.length;i++){
printf("%d",A.data[i]);
}
printf("\n");
//扩展二进制
B.length=0;
for(i=0;i<A.length;i++){
if(A.data[i]==1){
B.data[B.length++]=0;
B.data[B.length++]=1;
}else if(A.data[i]==0){
B.data[B.length++]=0;
}
}
//逗号二进制
B.data[B.length++]=0;
B.data[B.length++]=1;
B.data[B.length++]=1;
B.data[B.length++]=0;
//转换二进制数输出
printf("扩展后二进制输出为:\n");
for(i=0;i<B.length;i++){
printf("%d",B.data[i]);
}
printf("\n");
c[0]=0;
//图灵机转换,遍历二进制数组
for(i=0;i<B.length;i++){
c[1]=B.data[i];
if(c[0]==0&&c[1]==0){
c[0]=0;
B.data[i]=0;
printf("执行命令结果为:%d\n",B.data[i]);
}
else if(c[0]==0&&c[1]==1){
c[0]=1;
B.data[i]=0;
printf("执行命令结果为:%d\n",B.data[i]);
}
else if(c[0]==1&&c[1]==0){
c[0]=0;
B.data[i]=1;
printf("执行命令结果为:%d\n",B.data[i]);
}
else if(c[0]==1&&c[1]==1){
c[0]=10;
B.data[i]=0;
}
else if(c[0]==10&&c[1]==0){
c[0]=11;
B.data[i]=1;
printf("执行命令结果为:%d\n",B.data[i]);
}
else if(c[0]==11&&c[1]==0){
c[0]=0;
B.data[i]=1;
printf("执行命令结果为:%d\n",B.data[i]);
}
if(c[0]==11&&c[1]==0){
break;
}
}
//遍历结束后,未满足停止条件,补0继续
while(c[0]!=11&&c[1]!=0){
B.data[B.length]=0;
c[1]=B.data[B.length];
B.length++;
if(c[0]==0&&c[1]==0){
c[0]=0;
B.data[i]=0;
}else if(c[0]==0&&c[1]==1){
c[0]=1;
B.data[i]=0;
}
else if(c[0]==1&&c[1]==0){
c[0]=0;
B.data[i]=1;
}else if(c[0]==1&&c[1]==1){
c[0]=10;
B.data[i]=0;
}else if(c[0]==10&&c[1]==0){
c[0]=11;
B.data[i]=0;
}else if(c[0]==11&&c[1]==0){
c[0]=0;
B.data[i]=1;
}
}
//满足停止条件,将该位置变1,再加0
B.data[B.length++]=1;
B.data[B.length++]=0;
printf("XN×2数最终结果为:");
for(i=0;i<B.length;i++){
printf("%d",B.data[i]);
}
printf("\n");
//再次转换为二进制
A.length=0;
for(i=0;i<=B.length-3;i++){
if(B.data[i]==0&&B.data[i+1]==1&&B.data[i+2]==0){
A.data[A.length++]=1;
}else if(B.data[i]==0&&B.data[i+1]==0){
A.data[A.length++]=0;
}
}
//寻找第一个不为0的数;
i=0;
while(A.data[i]==0){
i++;
}
printf("XN×2的二进制数为:");
for(i;i<A.length;i++){
printf("%d",A.data[i]);
}
//转换十进制
for(i=A.length-1;i>=0;i--){
sum+=A.data[i]*(int)pow(2,(A.length-1-i));
}
printf("\n");
printf("输出的二进制为:%d\n",sum);
printf("\n");
return 0;
}
4.调试,测试及运行结果
①转化二进制的调试
②扩展二进制的调试
③执行图灵机命令的调试
④缩进二进制调试
⑤转化十进制
⑥当输入的十进制为负数时
⑦运行结果
测试
5.经验归纳
看到题目是不应该直接上手开始写代码,首先要思考用那种方法会使自己的代码尽量简单并且条理清晰。我刚开始编写程序时,惯性思维是用一个主函数把程序写完,但是这种想法让我思路比较混乱,在编写过程中遇到了很多很多的问题,循环语句中i的范围不好找,if语句的嵌套经常出错,包括数组的使用中也出现了很多问题。经同学提醒用了结构体,果然在循环这块变的简单了点,并且思路也清晰了很多。所以在以后的编程中应该多想几种方法,然后选择适合自己的一种。