第二次上机实验报告
实验名称:
模拟图灵机
实验内容:
以XN×2为例,模拟实现图灵机的运算过程
算法设计:
-
总体流程
-
输入一个十进制数
-
转换为二进制数
-
将二进制数拓展为二进位表示
-
执行XN×2,获得结果的二进位字符串
-
将二进位字符串压缩为二进制表示
-
将二进制数转为十进制整数
-
核心算法(XN×2)
输入二进位字符串
扫描字符串中的每个字符
将字符读入图灵机
将此时图灵机状态与标准状态比较,得到新的状态
用新的状态覆盖字符串
字符串指针右移
返回拓展后的字符串
调试截图:
-
二进位编码拓展调试
图 3 二进位编码拓展 -
二进位编码压缩调试
图 4 二进位编码压缩
结果测试
遇到的困难及解决方案:
-
二进制与十进制的相互转换。在模拟图灵机的过程中,需要多次实现二进制数字与十进制数字的相互转换。自己实现的转换方法受到数据类型等因素的限制,故直接采用Java中Interger类中的方法实现。
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int decNum = 0;
// 输入十进制数字
System.out.print("Dec:");
Scanner sc = new Scanner(System.in);
decNum = sc.nextInt();
// 转换为二进制数字的字符串形式
// 参数为十进制整型数字
// 返回值为二进制字符串
String binNum = Integer.toBinaryString(decNum);
System.out.println("Bin:" + binNum);
// 二进制字符串转为十进制整型数字
// 第一个参数为String类型的字符串,第二个参数为进制数,默认为10进制
// 返回值为整型数字
decNum = Integer.parseInt(binNum, 2);
System.out.println("Dec:" + decNum);
sc.close();
}
}
-
“可变字符串”StringBuilder类的应用。在处理“纸带”与“内态”的变化时,往往会出现字符串的长度变化、增加、删除等操作。而普通的字符串String类的长度是固定的,增加删除某个字符的实现也较为复杂,因此采用StringBuilder类完成对字符串的相关操作,以达到简化编程的效果。
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String str = "I love XUST";
// 可以直接用String初始化,也可以不带参数
StringBuilder sb = new StringBuilder(str);
System.out.println("StringBuilder:" + sb);
// length方法,返回当前字符串的长度
System.out.println("Length:" + sb.length());
// append方法,在字符串末尾添加
sb.append("!");
System.out.println("Append:" + sb);
// insert方法,第一个参数为插入的下标,第二个为插入的元素
sb.insert(1, " do");
System.out.println("Insert:" + sb);
// deleteCharAt方法,删除指定下标的字符
sb.deleteCharAt(0);
System.out.println("deleteCharAt:" + sb);
// toString方法,转化为String对象
str = sb.toString();
System.out.println("String:" + str);
}
}
算法具体实现:
/**
* All rights Reserved, Designed By YanCX
* @Title: TuringDemo.java
* @Package turingmachine
* @Description: TODO XN×2
* @author: YanCX
* @date: 2019年3月21日 下午4:38:34
* @version V1.0
* @Copyright: 2019 All rights reserved.
*/
package turingmachine;
import java.util.Scanner;
/**
* @ClassName: TuringDemo
* @Description: XN×2
* @author: YanCX
* @date: 2019年3月21日 下午4:38:34
*/
public class TuringDemo {
/**
* @Title: main
* @Description: XN×2
* @param: @param args
* @return: void
* @throws
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int num = 0;
// 输入十进制数字
System.out.print("Dec:\t");
Scanner sc = new Scanner(System.in);
num = sc.nextInt();
String str = DecToBin(num);
str = expandCode(str);
System.out.println("Expand:\t" + str);
str = contactCode(str);
System.out.println("Bin:\t" + str);
num = BinToDec(str);
System.out.println("Dec:\t" + num);
sc.close();
}
// 十进制转二进位字符串
public static String DecToBin(int decNum) {
String result = ""; // 保存返回结果的字符串
// 十进制转二进制
String binNum = Integer.toBinaryString(decNum);
System.out.println("Bin:\t" + binNum);
// 拓展成二进位
StringBuilder sb = new StringBuilder(binNum);
for (int i = 0; i < sb.length(); i++) { // 数组长度随时改变
if (sb.charAt(i) == '1') {
sb.insert(i + 1, '0');
i++;
} else {
continue;
}
}
// 末尾加逗号,即110
sb.append("110");
// System.out.print(sb);
result = sb.toString();
return result;
}
// 拓展二进位编码
public static String expandCode(String biString) {
StringBuilder sb = new StringBuilder(biString);
// 在二进位字符串前后各加一个0,防止位数不足导致出错
sb.insert(0, "0");
sb.append("0");
int[] state = new int[2];
state[0] = 0; // 内态
state[1] = 0; // 当前纸带上的值
for (int i = 0; i < sb.length(); i++) {
// System.out.println("i=" + i);
// 每一步的状态
System.out.println("i=" + i + "\t" + sb);
// 扫描到第i个字符串
state[1] = (int) (sb.charAt(i) - '0');
// System.out.println("state[0]=" + state[0] + "\tstate[1]=" + state[1]);
// 将此时的内态与标准内态比较,得到下一内态
if (state[0] == 0 && state[1] == 0) {
// 0 0->0 0
continue;
} else if (state[0] == 0 && state[1] == 1) {
// 0 1->1 0
state[0] = 1;
state[1] = 0;
} else if (state[0] == 1 && state[1] == 0) {
// 1 0->0 1
state[0] = 0;
state[1] = 1;
} else if (state[0] == 1 && state[1] == 1) {
// 1 1->10 0
state[0] = 10;
state[1] = 0;
} else if (state[0] == 10 && state[1] == 0) {
// 10 0->11 1
state[0] = 11;
state[1] = 1;
} else if (state[0] == 11 && state[1] == 0) {
// 11 0->0 1stop
state[0] = 0;
state[1] = 1; // stop
}
// 用此内态的扫描端覆盖原字符串,注意内态的位数
sb.deleteCharAt(i);
sb.insert(i, state[1]);
// for test
// System.out.println(i+ ":\t" + sb);
}
// 去掉字符串前后的0
boolean flag0 = true;
// 去掉字符串之前的0
while (flag0) {
if (sb.charAt(0) == '0') {
sb.deleteCharAt(0);
} else {
flag0 = false;
}
}
// 去掉字符串之后的0
flag0 = true;
while (flag0) {
if (sb.charAt(sb.length() - 1) == '0') {
sb.deleteCharAt(sb.length() - 1);
} else {
flag0 = false;
}
}
// 在字符串前后各加一个0
sb.insert(0, 0);
sb.append(0);
// for test
// System.out.println("sb:\t" + sb);
String expandCode = sb.toString();
return expandCode;
}
// 压缩二进制编码
public static String contactCode(String expandCode) {
String contactCode = "";
StringBuilder sb = new StringBuilder(expandCode);
StringBuilder result = new StringBuilder();
// 删去末尾的110
for (int i = 0; i < 3; i++) {
sb.deleteCharAt(sb.length() - 1);
}
// System.out.println("删去末尾的110:\t" + sb);
// 统计1的数量
int num1 = 0;
for (int i = 0; i < sb.length(); i++) {
// 遇到0就初始化
if (sb.charAt(i) == '0') {
result.append(num1);
num1 = 0;
} else {
num1++;
}
}
result.deleteCharAt(0);
contactCode = result.toString();
return contactCode;
}
// 将二进制编码转为十进制数字
public static int BinToDec(String biCode) {
int decNum = 0;
decNum = Integer.parseInt(biCode, 2);
// for test
// System.out.print("decNum:=" + decNum);
return decNum;
}
}