天天看點

圖靈機UN*2

一.題目分析

題目要求:根據的圖靈機的工作原理求出任意一個數的二倍數

題目分析:先将該數字由十進制轉換成對應的二進制碼,然後進行擴充。然後根據圖靈機的工作原理對擴充二進制碼進行計算,然後進行收縮,最後将普通二進制碼轉換成十進制碼

二.算法構造

1.先将輸入的十進制轉換成對應的二進制碼

2.根據圖靈機的擴充規則将普通二進制代碼進行擴充

規則:0->0

1->10

,(逗号)->110

然後在倆段加上無限個0(為了友善計算,将存放擴充二進制代碼的第一個數組元素設定成0)

3.根據圖靈機的計算規則,将擴充後的二進制代碼進行計算

規則:内态 輸入 改變後的内态 輸出

0 0 -> 0 0 右移

0 1 -> 1 0 右移

1 0 -> 0 1 右移

1 1 -> 10 1 右移

10 0 -> 11 1 右移

11 0 -> 0 1 停機

4.将擴充後的二進制碼進行收縮,從數組的第一位開始比較,如果第一位數組元素的值與相鄰的數組元素值相等,那麼隻可能是00的情況了,将收縮的數組元素指派為0,i++,下個元素與相鄰的元素再進行比較。如果不相等就是10或01的情況,将收縮後的數組元素指派為1,i=i+2,然後第i個數組元素再與相鄰的元素進行比較。

5.将收縮後的二進制代碼轉換成十進制,輸出

三.算法實作

程式源代碼:

package turing1;

import java.util.Scanner;//導包

public class Turing1 {

public static void main(String[] args)

{

int[] farray= new int[15];//用來存放擴充前的二進制碼

int[] sarray= new int[30];//用來存放擴充後的二進制碼

int[] tarray= new int[15];//用來存放收縮後的二進制碼

Scanner sc=new Scanner(System.in);//建立鍵盤錄入對象

System.out.println(“請輸入要計算的數字”);

int input=sc.nextInt();

//将十進制的數先轉換成二進制數,然後轉換成擴充後的二進制碼

int flength=CreatBinary(input,farray,sarray);

//根據圖靈機的轉換規則,将擴充後的二進制碼進行計算

int tlength=Stransform(flength,sarray);

//将擴充後的二進制碼轉換成普通的二進制碼,然後轉換成十進制碼

Shrink(tlength,sarray,tarray);

}

//将十進制的數先轉換成二進制數,然後轉換成擴充後的二進制碼
public static int CreatBinary(int input,int farray[],int sarray[])
{
	int i=0;//用來存放二進制碼的長度
	//将十進制數轉換成二進制數
	while(input!=0)
	{
		farray[i]=input%2;//通過取餘和整除的方法求出二進制碼
		input/=2;
		i++;
	}
	for(int j=0;j<i/2;j++)//将二進制碼逆序排列
	{
		int temp=farray[j];
		farray[j]=farray[i-j-1];
		farray[i-j-1]=temp;
	}
	//将二進制碼進行擴充
	int k=1;//從下标為1的數組開始計算,下标為0數組的設定為0
	for(int j=0;j<i;j++)
	{
		//擴充規則:0->0,1->10,逗号->110
		if(farray[j]==1)
		{
			sarray[k]=1;
			sarray[k+1]=0;
			k+=2;
		}
		else
		{
			k++;
		}
	}
	sarray[k]=1;
	sarray[k+1]=1;
	sarray[k+2]=0;
	k+=3;
	System.out.print("這個數字的擴充二進碼是:");
	for(int j=0;j<k;j++)
		System.out.print(sarray[j]);
	System.out.println(" ");
	return k;
}

//根據圖靈機的轉換規則,将擴充後的二進制碼進行計算
public static int Stransform(int k,int sarray[])
{int flag=0;//表示圖靈機的内态
for(int j=0;j<=k;j++)//圖靈機的轉換規則
{
	if(flag==0&&sarray[j]==0)//0 0 -> 0 0 R
	{
		sarray[j]=0;
		System.out.println("内态由 0 變成 0,輸入為 0 ,輸出為 0 ,右移");
	}
	else if(flag==0&&sarray[j]==1)//0 1-> 1 0 R 
	{
		sarray[j]=0;
		flag=1;
		System.out.println("内态由 0 變成 1,輸入為 1,輸出為 0,右移");
	}
	else if(flag==1&&sarray[j]==0)// 1 0 -> 0 1 R
	{
		sarray[j]=1;
		flag=0;
		System.out.println("内态由 1 變成 0,輸入為 0 ,輸出為 1,右移");
	}
	else if(flag==1&&sarray[j]==1)// 1 1-> 10 0 R
	{
		flag=10;
		sarray[j]=0;
		System.out.println("内态由 1 變成 10,輸入為 1 ,輸出為 0 ,右移");
	}
	else if(flag==10&&sarray[j]==0)// 10 0 -> 11 1 R
	{
		flag=11;
		sarray[j]=1;
		System.out.println("内态由 10 變成11,輸入為 0 ,輸出為 1 ,右移");
	}
	else// 11 0 -> 0 1 STOP
	{
		flag=0;
		sarray[j]=1;
		System.out.println("内态由 11 變成 0,輸入為 0 ,輸出為 1 ,停機");
		break;
	}
}
System.out.print("計算以後的擴充二進碼為:");
k+=2;
for(int j=0;j<k;j++)
	System.out.print(sarray[j]);
return k;
	
}

//将擴充後的二進制碼轉換成普通的二進制碼,然後轉換成十進制
public static void Shrink(int k,int sarray[],int tarray[])
{
	int m=0,n=0;
	while(m<k-4)//由于最後三位是110,表示逗号,是以不考慮
	{
		if(sarray[m]==sarray[m+1])//如果相鄰的倆個數相等,一定是00的情況
		{
			tarray[n]=0;//對應普通的二進制碼就是0
			n++;
			m++;
		}
		else//如果相鄰的倆個數不想等,一定時10或01的情況
		{
			tarray[n]=1;//對應的普通二進制碼就是1
			n++;
			m=m+2;
		}
	}
	System.out.println(" ");
	System.out.print("收縮以後的二進制碼為:");
	for(int j=0;j<n;j++)
		System.out.print(tarray[j]);
	int output=0;//輸出結果
	int leap=1;//二進制的位數
	for(int j=n-1;j>-1;j--)
	{
		if(tarray[j]==1)
		{
			output+=leap;
			leap*=2;
		}
		else
			leap*=2;
	}
	System.out.println(" ");
	System.out.println("計算結果為:"+output);
}
           

}

四.調試、測試及運作結果

調試:

一開始在對擴充二進制碼進行計算的時候為了友善,直接采用6個ify語句進行計算,結果發生了錯誤

圖靈機UN*2

結果顯示:

圖靈機UN*2

發現錯誤後将6個if語句寫成了if語句的嵌套,最後擴充正确

測試:

1.測試輸入一個任意十進制的數字将其裝換成二進制碼,然後根據圖靈機的擴充規則得到相應的擴充二進制碼

圖靈機UN*2

調試結果:

圖靈機UN*2

2.測試将擴充後的二進制代碼通過圖靈機計算的規則進行計算

圖靈機UN*2
圖靈機UN*2

測試結果:

圖靈機UN*2

3.測試将計算計算後的二進制碼收縮成普通二進制碼,最後轉換成十進制數

圖靈機UN*2
圖靈機UN*2

測試結果:

圖靈機UN*2

運算結果:

1.輸入5

結果為:

圖靈機UN*2

2.輸入11

結果為:

圖靈機UN*2

3.輸入34

結果為:

圖靈機UN*2

五.經驗歸納

1.在解決一個問題的是時候,先不要忙的程式設計式。首先在計算本上先舉一些具體的例子來驗證自己的想法是否正确。如果有錯誤,應該認真的改正

2.在編寫程式的過程中,如果遇到一些思路上難以了解的東西,多于其他同學進行讨論,說不定在讨論的過程中,就會明白問題的本質

3.在編寫程式的時候,千萬不能投機取巧進而省略一些步驟。例如在計算擴充二進制碼的時候,為了簡單,直接用若幹個if。最後還是改成了if的嵌套,浪費了大把的時間。

4.更加體會到了在編寫程式的過程中,寫注釋的一些好處