基于JAVA面向对象设计模拟图灵机运行过程

图灵机引言

图灵机是一种思想模型,是关于数据、指令、程序以及程序/指令自动执行的基本思想。按照计算规则(程序)对输入进行变换得到输出。输入/输出都是0和1 形式的表达,程序和指令也是0和1 的形式表达。
图灵机(XN×2)的运算指令(第一列为内态,第二列为读入字符,第三列为改变后指令运行后的内态,第四列为执行指令后读出的字符):

  • 0 0 → 0 0 R
  • 0 1 → 1 0 R
  • 1 0 → 0 1 R
  • 1 1 → 10 0 R
  • 10 0 → 11 1 R
  • 10 1 → 0 0 R
  • 11 0 → 0 1 STOP
  • 11 1 → 0 0 R

图灵机运行原理

其运算的原理大致为:

  • 获得一个整数,转为二进制
  • 再转为二进位编码(如数字3,其二进制为11,二进位编码为01001011)
  • 再利用上述指令对“输入字符”进行读写,输出一个“输出字符串”
    PS:扩展二进位编码,11表示逗号

设计思路

  • 大体思路就是图灵机的运行原理。先从键盘获取一个整数,将输入数值转换为二进制,输出转换后的二进制。将二进制转换为二进位扩展编码并输出转换后的二进位扩展编码,将扩展编码字符串变量转为字符数组,通过if-else嵌套语句根据内态和读入的字符完成读写,输出每轮运行的字符串,最后输出最终的结果。
  • 在设计十进制转为二进制的函数功能上,直接调用**Integer.toBinaryStr-ing()**函数可直接求得;
  • 将二进制转为二进位数值编码,是本次实践的一个难点。先定义2个字符串,一个字符串储存转换后的二进制字符串,另一个字符串储存字符全为0的字符串(且这个全为0字符串的体积是源字符串体积的三倍,这是为了防止转为二进位扩展编码,字符串体积不够)。
  • 这个功能采用对两个栈的操作来实现,第一个栈stack1存取二进制字符数组,第二个栈stack2存储所有字符全为0的字符数组。利用stack1的指针top读取arr数组的每一位字符元素。如果读取的字符为1,则往栈stack2中依次添加0、1、0字符;如果读取的字符为0,则往栈stack2中添加字符0。当栈stack1的指针top到达栈顶便停止,输出结果即为stack2存储的字符数组。
  • 模拟图灵机的指令运行原理,利用if-else嵌套语句,对内态和读入的字符的八种情况进行判断,当执行到内态为内态为1 0,读入字符为1便停止。

流程图

在这里插入图片描述

源码实现

package com.Turin;
/**
 * 定义一个栈,存储二进制字符
 * @author 万物甦醒
 * 编辑时间:2019年3月20日
 */
public class charStack1 {
	public int volume;//定义数组的体积
	public int top;    
	char[] elem=new char[volume];//定义字符数组
	
	public charStack1(int volume, int top, char[] elem) 
	{
		this.volume = volume;
		this.top = top;
		this.elem = elem;
	}
}
package com.Turin;
/**
 * 定义一个栈,里面字符全为1
 * @author 万物甦醒
 *编辑时间:2019年3月20日
 */
public class charStack2 {
	public int volume;//定义数组的体积
	public int top;    
	char[] elem=new char[volume];//定义字符数组
	
	public charStack2(int volume, int top, char[] elem) {
		this.volume = volume;
		this.top = top;
		this.elem = elem;
	}
}
package com.Turin;

/**java
 * 定义一个Transfer类用于实现一些数制转换的基本功能
 * 主要来实现以下两个功能:
 * 1.十进制转为二进制
 * 2.将二进制转为二进位数值编码
 *   2.1 2个字符串,一个字符串储存转换后的二进制字符串,另一个字符串储存字符全为0的字符串
 *      (且这个全为0字符串的体积是源字符串体积的三倍)
 *   2.2 二进位数值编码采用对两个栈的操作来实现,第一个栈为二进制字符串,第二个栈字符全为0
 *
 * @author 万物甦醒
 * 第1次编辑时间:2019年3月19日
 * 第2次编辑时间:2019年3月20日
 */
public class Transfer {
	String binaryConversion(int number)   //十进制转为二进制
	{
		return Integer.toBinaryString(number);//将十进制转为二进制
	}
	

	
	String codingConversion(String arr)//将二进制转换为二进位编码
	{
		String arrs=expandStringSize(arr);   //给字符串2倍扩容 ,在其基础上后被多添2倍的0
		
		char[] ar1=arr.toCharArray();//将原字符串变量转为字符数组
		char[] ar2=arrs.toCharArray();//将字符串变量转为字符数组,全为0
		
	
		//定义两个栈,一个栈存源字符,另一个栈为字符全为0,且数组体积是原来的3倍,
		charStack1 stack1=new charStack1(arr.length()+2,0,ar1);
		charStack2 stack2=new charStack2(arrs.length()+2,0,ar2);
		
		while(stack1.top<arr.length())        //栈指针到栈顶前
		{
			if(stack1.elem[stack1.top]=='1')  //如果读取到字符为1
			{
				//往栈2中依次添加0、1、0;
				stack2.elem[stack2.top]='0';
				stack2.elem[++stack2.top]='1';
				stack2.elem[++stack2.top]='0';
			}
			else if(stack1.elem[stack1.top]=='0')//如果读取到的字符为0
			{
				//往栈2中添加1个零
				stack2.elem[++stack2.top]='0';
			}
			stack1.top++;//栈指针上移
		}
		stack2.elem[++stack2.top]='1';
		stack2.elem[++stack2.top]='1';
		
		String arra=String.valueOf(stack2.elem);//再将字符数组转为字符串
		return arra;
	}
	
	public String expandStringSize(String arr)//扩容3倍字符串体积
	{
		
		String arrs=arr;                     //获取原先的字符串
		char[] status = arrs.toCharArray();  //字符串转为字符数组
		for(int m=0;m<arr.length();m++)      //字符数组每位初始化为0
			status[m]='0';
		String status1=String.valueOf(status);//再将字符数组转为字符串
		if(arr.length()<3)
		{
			return status1+status1+status1+status1+status1+status1;
			}
		else 
		{
			return status1+status1+status1;
		}//返回字符串

	}
	
}

package com.Turin;
import java.util.Scanner;

/**
 * 仿制图灵机原理(XN×2)由扩展的二进位依据指令输出
 * 思路: 	1.用户随机输入符合条件的二进位扩展编码
 * 	2.字符串类型arr保存输入编码,转为字符数组
 * 	3.根据内态和读入字符按照运算指定模仿图灵机工作
 * @author 万物甦醒
 * 第1次编辑时间:2019年3月19日
 * 第2次编辑时间:2019年3月20日
 */
public class Turin {

	public static void main(String[] args) 
	{	
		Transfer tran=new Transfer();//定义转化编码的自定义对象
		Scanner scan=new Scanner(System.in);
		
		System.out.println("请输入一个十进制整数");
		
		int number=scan.nextInt();//键盘上获取一个整数
		scan.close();
		
		//将输入数值转换为二进制,输出转换后的二进制
		System.out.println("数值转换成二进制为:"+tran.binaryConversion(number));
		
		
		//将二进制转换为二进位扩展编码,输出转换后的二进位扩展编码
		String arr=tran.codingConversion(tran.binaryConversion(number));
		System.out.println("转换后的二进位扩展编码为:"+arr);

		//将扩展编码字符串变量转为字符数组
		char[] ar=arr.toCharArray();
		
		int flag=0;					//定义一个变量记录内态
		/**
		 * 图灵机(XN×2)的运算指令
		 *  0 0 →  0 0 R
		 *  0 1 →  1 0 R
		 *  1 0 →  0 1 R
		 *  1 1 → 10 0 R
		 * 10 0 → 11 1 R
		 * 10 1 →  0 0 R
		 * 11 0 →  0 1 STOP
		 * 11 1 →  0 0 R
		 */
		for(int i=0;i<arr.length();i++)  //根据内态值和读入字符值按指令输出
		{	
			if(ar[i]==' ')
				break;
			if(ar[i]=='0'&flag==0)
			{
				flag=0;
				ar[i]='0';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
			else if(ar[i]=='1'&flag==0)
			{
				flag=1;
				ar[i]='0';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
			else if(ar[i]=='0'&flag==1)
			{
				flag=0;
				ar[i]='1';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
			else if(ar[i]=='1'&flag==1)
			{
				flag=10;
				ar[i]='0';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
			else if(ar[i]=='0'&flag==10)
			{
				flag=11;
				ar[i]='1';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
			else if(ar[i]=='1'&flag==10)
			{
				flag=0;
				ar[i]='0';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
			else if(ar[i]=='0'&flag==11)
			{
				flag=0;
				ar[i]='1';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
				System.out.println("字符串再第"+(i+1)+"位停止继续读入");
				break;
			}
			else if (ar[i]=='1'&flag==11)
			{
				flag=0;
				ar[i]='0';
				System.out.print("第"+(i+1)+"轮的结果为:");
				System.out.println(ar);
			}
		}
		//输入读完后的字符串
			System.out.print("图灵机最终输出字符串为:");
			System.out.print(ar);
	}
	}

运行结果展示

十进制5运行结果截图十进制11运行结果截图

心得

  • 由于第一次用Java编写本学科的实验题目,在编译过程中发现了一些低级的语
    法错误。和C/C++语法混淆,Java语言的与运算符是“&”,而非C/C++的“&&”。由于这个原因在调试过程中一直不明白是什么原因。另外while()语句括号里必须是布尔类型的表达式,而不能像C语言那样可以用一个非零值。

  • 将二进制转为二进位数值编码,是本次实践的一个难点。先定义2个字符串,一个字符串储存转换后的二进制字符串,另一个字符串储存字符全为0的字符串,且这个全为0字符串的体积是源字符串体积的三倍,这是为了防止转为二进位扩展编码,字符串体积不够)。但也是因为字符数组的体积问题遇到了top的值显然溢出数组的体积大小的情况,导致的异常。改进方式如下:
    在public String expandStringSize(String arr)函数中添加如下代码:

		if(arr.length()< 3)
		{return status1+status1+status1+status1+status1+status1; }
		else 
		{return status1+status1+status1;} 
  • 通过扩大更大的字符串的长度解决溢出问题。所以在使用栈这个数据结构,要考虑好数组溢出的可能性。
  • 尽管代码实现了要求,但在public String expandStringSize(String arr)这个扩容字符串显然这个不是最优算法,字符串字符数组来来回回的转化显得麻烦,增加程序的时间复杂度。
  • 本次算法设计中涉及到最多的语法点,之前上前很少接触个如此巨大的和”字符”打交道”的程序,也遇到了不少的问题。以下是本人在本次编程总结的和字符串、字符数组有关的几个函数或语法:
    字符串转化为字符数组:
    char[] status = arrs.toCharArray();
    (其中arrs是字符串对象,status是字符数组名)
    字符数组转化为字符串:
    String status1=String.valueOf(status);
    (其中status是字符数组名)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值