Java编写程序模拟XN*2图灵机
一、内容:
对于XN*2图灵机进行模拟,任意给定的十进制数a,转换为收缩扩展二进制的编码,再编程模拟此Turing机的运行过程,要求输出从开始运行起的每一步骤的结果。 用C或C++或java或python语言实现程序解决问题。
1.程序风格良好(使用自定义注释模板)
2.提供友好的输入输出,并进行输入数据的正确性验证。
二、步骤:
1.算法
(1)从键盘输入一个数,判断其是否为正整数,若不是正整数输出“您输入的数字有误,请输入一个十进制的正整数”,若为十进制正整数进行第二步。
(2)将该数转换为收缩扩展二进制的编码。
(3)根据xn*2图灵机的计算规则处理。
计算规则:
内态为0 输入为0时 ,内态变为0 输出为0 向右移动
内态为0 输入为1时 ,内态变为1 输出为0 向右移动
内态为1 输入为0时 , 内态变为0 输出为1 向右移动
内态为1 输入为1时 , 内态变为10 输出为0 向右移动
内态为10 输入为0时 ,内态变为11 输出为1 向右移动
内态为11 输入为0时,内态变为0 输出为1 结束
(4)将运算后的二进制数的后三位(逗号)去掉,并将二进制数转换为十进制数,并输出结果。
2.概要设计
流程图如下图2.2.1所示:
3.测试
(1)如图2.3.1,当输入3.5是程序报错,因为编写程序时规定输入的数必须为整形。
(2)如图2.3.2,当输入为负数时,输出“您输入的数字有误,请输入一个十进制的正整数”。
(3)如图2.3.3,当输入一个正整数时,根据xn*2图灵机规则运算输出。
4.调试
(1)当输入3时编码正确如图2.4.1
(2)继续运行,直至运行到内态为11,输入为0,时不再向后运行而直接输出,如图2.4.2
解决方案:因为运行到最后一位就输出,无法执行向右移动,从而无法将最后一位输出,所以应该将逗号转译为1100,使得最后一位操作后还可以再向右移动,从而输出最后一位。
5.心得体会
(1)在添加逗号时,应该添加“1100”而非“110”,对比下面两幅图可知,当添加“110”时,由于最后一位执行时无法再向右移动,而造成最后一位无法输出,导致无法计算出正确结果。
解决方法:将sb.append(“110”);//110添加给sb。改为sb.append(“1100”);//1100添加给sb。及将逗号编写为1100
(2)刚开始没有考虑到输入的数为负数,导致输入为负数时,会出现乱码之类的情况,后增加一条判断语句,如果为正数时才进行运算,非正数时则输出提示错误信息。
(3)刚开始写程序时,准备自己写二进制和十进制之间的转换方法和字符串转化,后来查找资料发现StringBuffer类提供了大量的字符串操作的方法,在以后的编写过程中可以提前查找是否存在现成的类或函数可以使用,这样可以大大减少代码编写的量。
三、源代码:
/**
*@Title:Turing.java
*@Package:Turing
*@Description:TODO(判断改日期是打鱼还是晒网)
*@author:YuanQuan
*@date:2021年4月11日 下午8:22:15
*@version 1.0
*/
package Turing;
import java.util.Scanner;
/**
* @ClassName:Turing
* @Description:TODO(模拟xn*2图灵机)
* @author:YuanQuan
* @Date:2021年4月11日 下午8:22:15
*
*/
public class Turing {
/**
* @Title:change
* @Description:TODO(将十进制数转换为收缩扩展二进制的编码)
* @param:@param a
* @param:@return
* @return:StringBuffer
* @param a
* @return
*/
static StringBuffer change(int a)
{
String s;
s = Integer.toBinaryString(a);//将10进制数转为32位的2进制数
StringBuffer sb = new StringBuffer(s.replace("1", "10"));
sb.append("1100");//1100添加给sb。
return sb;
}
/**
* @Title:rules
* @Description:TODO(图灵机xn*2的规则)
* @param:@param sb
* @return:void
* @param sb
*/
static void rules(StringBuffer sb)
{
int inner=0;//内态
for(int i = 0;i<sb.length();i++)
{
//内态为0,输入为0时,操作后内态为0,输出为0,向右移动
if(inner==0 && sb.charAt(i)=='0') //charAt返回指定索引处的字符
{
inner=0;
sb.setCharAt(i, '0');//setcharAt将字符串中指定的位置的字符替换成目标字符
System.out.println("内态为0,输入为0,操作后为:" +sb+ "此时内态为:" +inner+ "输出为:" +sb.charAt(i));
continue;
}
//内态为0,输入为1时,操作为内态变为1,输出为0,向右移动
if(inner==0 && sb.charAt(i)=='1')
{
inner=1;
sb.setCharAt(i, '0');
System.out.println("内态为0,输入为1,操作后为:" +sb+ "此时内态为:" +inner+ "输出为:" +sb.charAt(i));
continue;
}
//内态为1,输入为0时,操作为内态变为0,输出为1,向右移动
if(inner==1 && sb.charAt(i)=='0')
{
inner=0;
sb.setCharAt(i, '1');
System.out.println("内态为1,输入为0,操作后为:" +sb+ "此时内态为:" +inner+ "输出为:" +sb.charAt(i));
continue;
}
//内态为1,输入为1时,操作为内态变为10,输出为0,向右移动
if(inner==1 && sb.charAt(i)=='1')
{
inner=10;
sb.setCharAt(i, '0');
System.out.println("内态为1,输入为1,操作后为:" +sb+ "此时内态为:" +inner+ "输出为:" +sb.charAt(i));
continue;
}
//内态为10,输入为0时,操作为内态变为11,输出为1,向右移动
if(inner==10 && sb.charAt(i)=='0')
{
inner=11;
sb.setCharAt(i, '1');
System.out.println("内态为11,输入为0,操作后为:" +sb+ "此时内态为:" +inner+ "输出为:" +sb.charAt(i));
continue;
}
//内态为11,输入为0时,操作为内态变为0,输出为1,结束
if(inner==11 && sb.charAt(i)=='0')
{
inner=0;
sb.setCharAt(i, '1');
System.out.println("内态为11,输入为0,操作后为:" +sb+ "此时内态为:" +inner+ "输出为:" +sb.charAt(i));
break;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.println("请输入一个整型的十进制正数:");
int b = in.nextInt();
if(b>=0)
{
StringBuffer sb = change(b);
System.out.println("编码后为:" +sb);
rules(sb);
System.out.println("二进制结果为:" +sb);
sb.delete(sb.length()-2, sb.length());
int c=Integer.parseInt(sb.toString().replace("10", "1"), 2);
System.out.println("十进制结果为:" +c);
}
else
{
System.out.println("您输入的数有误,请输入一个十进制的正整数");
}
}
}