一.题目分析
对于给定的一台图灵机(XN×2) 和任意给定的正整数进行转换字符,编程模拟此图灵机的运行过程,要求输出从开始运行起的每一步骤的结果。
在这里先要将正整数转换为二进制数,再进行进行扩展,图灵机(XN×2)在扩展的二进位上实现运算。之后,再将运算结果翻译为二进制,进而转换为十进制,就能得到原数的运算结果。
二.算法构造
在本次实验中,图灵机(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,
11 0->0 1 STOP.
箭头两边的加粗的数表示图灵机的内态,另外两数左边的数表示输入,右边的数表示输出,R、STOP表示图灵机的动作,R是向右移动一位,STOP是停止信号,在字符数组中用(0,1,1,0)判断。
就本次实验而言,我设置两个字符数组进行运算,第一个主要负责图灵机的运算,第二个负责得出图灵机的运算结果转化。在运算的过程中,我还设置两个数组长度标识,以及停止符的标识。
三.算法实现
import java.util.Scanner;
public class Tuling {
public static void main(String[] args){
System.out.print("请输入一个正整数:");
Scanner scan=new Scanner(System.in);
int m=scan.nextInt();
Data t=new Data();
t.trans(m);
System.out.print("二进制:");
System.out.println(t.data);
t.extend();
System.out.print("扩展为:");
System.out.println(t.data);
System.out.println("进行XN*2计算:");;
t.tuling_XN2();
System.out.print("翻译为:");
t.restore();
System.out.print("化为整数:"+t.power());
}
}
class Data{
public char[] data=new char[100]; //定义一个放置原数二进制的字符数组
public char[] value=new char[100]; //定义一个放置计算结果的字符数组
public int length=0; //定义整型表示第一个数组元素个数
public int leng=0; //定义整型表示第二个数组元素个数
public char[] arr= {'0','1','1','0'}; //初始化字符数组保存附加停止符
public boolean stop=false; //定义布尔型标志
void trans(int m){ //整数转二进制
int i=0;
char temp;
while(m!=0){ //除余2,整除得0,否则得1,再除以2,循环此过程,直到0
if(m%2==0)
data[i]='0';
else
data[i]='1';
i++;
m=m/2;
}
for(i=0;i<data.length;i++){
if(data[i]!='\0') length++; //计算数组元素
else break;
}
for(i=0;i<length/2;i++){ //将二进制改为从高位到低位顺序递增
temp=data[i];
data[i]=data[length-1-i];
data[length-1-i]=temp;
}
}
void extend(){ //二进制扩展
for(int i=0;i<length;i++){
if(data[i]=='1'){
for(int j=length;j>i;j--) //遇到1,就将后面的位置往后平移一个位置
data[j+1]=data[j];
data[i]='0';
data[i+1]='1';
length++;
i++;
}
}
for(int i=0;i<arr.length;i++) { //在数组后添加停止符
data[length++]=arr[i];
}
}
void tuling_XN2() { //图灵XN*2计算
int i=0;
String str;
String s="0"; //内态初始化
while(!stop) {
str=String.valueOf(data, 0, length); //在data数组上从0开始抓取length个字符形成字符串
System.out.println(i+1+":"+str+" 内态:"+s+",输入;"+data[i]);
if(data[i]=='0') {
if(s=="0") {
s="0";data[i]='0';i++; //0 0->0 0 R
}else if(s=="1") {
s="0";data[i]='1';i++; //1 0->0 1 R
}else if(s=="10") {
s="11";data[i]='1';data[i+1]='0'; //10 0->11 1 R
i++;length++;
}else if(s=="11") {
s="0";data[i]='1';data[i+1]='0';stop=true; //11 0->0 1 STOP
i++;length++;
}
}else {
if(s=="0") {
s="1";data[i]='0';i++; //0 1->1 0 R
}else {
s="10";data[i]='0';i++; //1 1->10 0 R
}
}
}
str=String.valueOf(data, 0, length);
System.out.println(i+1+":"+str+" 停止");
}
void restore() { //翻译为二进制
int j=0;
for(int i=1;i<length;i++) {
if(data[i]=='1') {
if(data[i+1]=='1') //遇到11跳出
break;
else {
value[j]='1';j++;leng++; //遇到1得1
}
}else if(data[i]=='0'&&data[i+1]=='0') {
value[j]='0';j++;leng++; //遇到00得0
}
}
System.out.println(value);
}
int power() { //还原整数
int sum=0;
for(int i=0;i<leng;i++) {
if(value[i]=='1')
sum+=(int)Math.pow(2, leng-1-i); //遇到1则计算当前位权,位权相加得到十进制
}
return sum;
}
}
四.调试、测试与运行结果
五.经验归纳
这次实验我主要学会了如何使用断点进行跟踪调试,刚开始按照自己的思路做下来时,每一个流程输出的结果都与我的设想有很大差距,通过跟踪后我很快明白主要的逻辑错误存在在哪里,在之前编程中出错后经常会从头看到尾来找bug,这次代码较长也让我有机会了解Eclipse的调试如何进行。
还有这次学会一个操作,将char[]数组转换为String型,借用String.valueOf()静态方法重载可以实现。