图灵机的模拟

一、实验目的

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语句的嵌套经常出错,包括数组的使用中也出现了很多问题。经同学提醒用了结构体,果然在循环这块变的简单了点,并且思路也清晰了很多。所以在以后的编程中应该多想几种方法,然后选择适合自己的一种。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值