实验目的
1.掌握图灵机的概念和基本结构,理解图灵机的基本指令和编码方式;
2.掌握图灵机的编程方法。
实验内容
对于任意给定的一台Turing机和任意给定的字符串w ( w不含空格),编程模拟此Turing机的运行过程,要求输出从开始运行起的每一步骤的结果。
解决思路
首先对题目内容进行了更改,用户输入一个整形数然后对该整形数进行操作,大致分为四部:
- 将整形数转化了二进制。
- 将二进制转化为扩展二进制。
- 运用XN*2机制对扩展二进制进行处理。
- 得到最终的扩展二进制,对它进行处理,还原成十进制。
整形数转化为二进制
- 首先用户输入一个整形数,而这处的输入数据也是整个代码唯一一处需要进行数据合法性判断的地方,这里采用try-catch解决:
System.out.print("请输入一个整数执行(XN*2)操作:");
int number = 0;
//处理不正确数据的输入
while(true)
{
Scanner scanner = new Scanner(System.in);
try {
number = scanner.nextInt();
break;
} catch (Exception e) {
// TODO: handle exception
System.out.print("输入错误,请重新输入一个整数:");
continue;
}
}
2.将整形数number转化为二进制并输出,这里采用StringBuffer类型存储转化为二进制的字符串,因为StringBuffer更利于后面的操作。
输出语句在主函数中,所有函数都封装在类Turing中,而从主函数中通过传参可以直接对StringBuffer类型的string进行数据更改;
void change(int number,StringBuffer string)
{
if(number != 0)
{
change(number/2,string);
string.append(number%2 == 1 ? "1":"0");
}
}
StringBuffer string = new StringBuffer();
turing.change(number,string); //将number转化为二进制
二进制转化为扩展二进制
1.首先二进制转化为扩展二进制,可以执行下面的操作:‘1’转化为"10",也就是在下一坐标加一个字符’0’,"0"可以不用管,在转化的时候需要遍历string,而且需要string里面的相对应的字符下标,这里先将StringBuffer类型的string转化为char arr[];然后进行遍历:
//将二进制转化为扩展二进制
void extendedBinary(int number,StringBuffer string)
{
int temp = 0;//StringBuffer改变一次,下一次应该插入的位置会加一
char arr[] = string.toString().toCharArray();
for (int i = 0; i < arr.length; i++) {
if(arr[i] == '1')
{
temp += 1;
string.insert(i+temp, "0");
}
}
System.out.println(number + "的扩展二进制为:" + string);
}
进行XN*2机制的运算,并输出每一步结果:
这里只要执行XN2的运算机制就行:
XN2机制
- 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,1STOP
//Turing机进行XN*2的操作
void xn(StringBuffer string)
{
String s = "0";//内态
int temp = 1; //执行步骤
string.append("110");
char arr[] = string.toString().toCharArray();
for (int i = 0; i <= arr.length; i++) {
if(s == "0" && arr[i] == '1')
{
s = "1";
string.setCharAt(i, '0');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if(s == "1" && arr[i] == '0')
{
s = "0";
string.setCharAt(i, '1');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if (s == "1" && arr[i] == '1') {
s = "10";
string.setCharAt(i, '0');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if (s == "10" && arr[i] == '0') {
s = "11";
string.setCharAt(i, '1');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if(s == "11") {
s = "0";
string.append("10");
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
}
}
进行最后的还原处理:
首先先将得到的扩展二进制转化为二进制:
首先上面得到没有转化之前的扩展二进制第一位是’1’,所以转化后第一位肯定是’0’,因为内态开始为’0’,所以先要删除string下标为0的字符,然后删除最后三位的字符串"110",然后还有重要一点,每删除一个字符,那么下次删除字符的下标应该减去执行删除操作的次数,因为char arr[]元素不会变,但是string的长度会减一:
//转化为二进制
void convertToBinary(StringBuffer string)
{
string.deleteCharAt(0);//删除扩展二进制刚开始的"0"
string.delete(string.length() -4, string.length() - 1); //删除扩展二进制后的"110"
char arr[] = string.toString().toCharArray();
int temp = 0;
for (int i = 0; i < arr.length; i++) {
if(arr[i] == '1' && arr[i+1] == '0')
{
string.deleteCharAt(i + 1 - temp);
temp += 1;
i += 1;
}
}
System.out.println("转化为二进制为:" + string);
}
将得到的二进制转化为十进制:
void toInt(StringBuffer string)
{
int sum = 0;
string.reverse(); //将字符串反转
char arr[] = string.toString().toCharArray();
for (int i = 0; i < arr.length; i++) {
if(arr[i] == '1')
{
sum += Math.pow(2, i);
}
}
System.out.println("执行完XN*2的十进制为:" + sum);
}
全部代码
import java.util.Scanner;
class Turing
{
//Turing机进行XN*2的操作
void xn(StringBuffer string)
{
String s = "0";//内态
int temp = 1; //执行步骤
string.append("110");
char arr[] = string.toString().toCharArray();
for (int i = 0; i <= arr.length; i++) {
if(s == "0" && arr[i] == '1')
{
s = "1";
string.setCharAt(i, '0');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if(s == "1" && arr[i] == '0')
{
s = "0";
string.setCharAt(i, '1');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if (s == "1" && arr[i] == '1') {
s = "10";
string.setCharAt(i, '0');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if (s == "10" && arr[i] == '0') {
s = "11";
string.setCharAt(i, '1');
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
else if(s == "11") {
s = "0";
string.append("10");
System.out.println("第" + temp + "次结果为:" + string + "\n内态为:" + s);
temp += 1;
}
}
}
void change(int number,StringBuffer string)
{
if(number != 0)
{
change(number/2,string);
string.append(number%2 == 1 ? "1":"0");
}
}
//将二进制转化为扩展二进制
void extendedBinary(int number,StringBuffer string)
{
int temp = 0;//StringBuffer改变一次,下一次应该插入的位置会加一
char arr[] = string.toString().toCharArray();
for (int i = 0; i < arr.length; i++) {
if(arr[i] == '1')
{
temp += 1;
string.insert(i+temp, "0");
}
}
System.out.println(number + "的扩展二进制为:" + string);
}
//转化为二进制
void convertToBinary(StringBuffer string)
{
string.deleteCharAt(0);//删除扩展二进制刚开始的"0"
string.delete(string.length() -4, string.length() - 1); //删除扩展二进制后的"110"
char arr[] = string.toString().toCharArray();
int temp = 0;
for (int i = 0; i < arr.length; i++) {
if(arr[i] == '1' && arr[i+1] == '0')
{
string.deleteCharAt(i + 1 - temp);
temp += 1;
i += 1;
}
}
System.out.println("转化为二进制为:" + string);
}
//转化为十进制
void toInt(StringBuffer string)
{
int sum = 0;
string.reverse(); //将字符串反转
char arr[] = string.toString().toCharArray();
for (int i = 0; i < arr.length; i++) {
if(arr[i] == '1')
{
sum += Math.pow(2, i);
}
}
System.out.println("执行完XN*2的十进制为:" + sum);
}
}
public class Main {
public static void main(String[] args) {
Turing turing = new Turing();
System.out.print("请输入一个整数执行(XN*2)操作:");
int number = 0;
//处理不正确数据的输入
while(true)
{
Scanner scanner = new Scanner(System.in);
try {
number = scanner.nextInt();
break;
} catch (Exception e) {
// TODO: handle exception
System.out.print("输入错误,请重新输入一个整数:");
continue;
}
}
StringBuffer string = new StringBuffer();
turing.change(number,string); //将number转化为二进制
System.out.println(number + "的二进制为:" + string);
turing.extendedBinary(number,string); //将二进制转化为扩展二进制
turing.xn(string); //进行XN*2机制
turing.convertToBinary(string);
turing.toInt(string);
}
}
总结
对XN*2的运算机制有了一定的了解,然后运用StringBuffer类型处理需要修改的字符串数据比String类型处理数据的效率较高。上面内容如果有什么问题,欢迎指正!