java实现格雷码生成

35 篇文章 1 订阅

  什么是格雷码?

         下面一段来自百度百科:

          在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码反射码。在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误。格雷码有多种编码形式。

     由此可见,使用格雷码可以让数字电路的变化趋于稳定。


特点

格雷码属于可靠性编码,是一种错误最小化的编码方式。
因为,虽然自然二进制码可以直接由数/模转换器转换成模拟信号,但在某些情况,例如从十进制的3转换为4时二进制码的每一位都要变,能使数字电路产生很大的尖峰电流脉冲。而格雷码则没有这一缺点,它在相邻位间转换时,只有一位产生变化。它大大地减少了由一个状态到下一个状态时逻辑的混淆。由于这种编码相邻的两个码组之间只有一位不同,因而在用于方向的转角位移量-数字量的转换中,当方向的转角位移量发生微小变化(而可能引起数字量发生变化时,格雷码仅改变一位,这样与其它编码同时改变两位或多位的情况相比更为可靠,即可减少出错的可能性。
格雷码是一种绝对编码方式,典型格雷码是一种具有反射特性和循环特性的单步自补码,它的循环、单步特性消除了随机取数时出现重大误差的可能,它的反射、自补特性使得求反非常方便。
由于格雷码是一种变权码,每一位码没有固定的大小,很难直接进行比较大小和算术运算,也不能直接转换成液位信号,要经过一次码变换,变成自然二进制码,再由上位机读取。
典型格雷码是一种采用绝对编码方式的准权码,其权的绝对值为2^i-1(设最低位i=1)。
格雷码的十进制数奇偶性与其码字中1的个数的奇偶性相同。


      那么格雷码有什么规律呢?当用一个二进制表示格雷码时,也就是n=1时,格雷码只有0,1;

       n=2时,格雷码是:00,01,11,10;

       n=3时,格雷码是:000,001,011,010,110,111,101,100;

       由此可见,格雷码都有一个普遍规律:
       第一:格雷码的个数为2的n次方。如n=3时,有8个格雷码。

       第二:格雷码的最高位有规律,前面一半为0,后面一半为1;

       第三:格雷码除去最高位后,是对称的。10对10,11对11.而且由n-1的格雷码组成。

      上面三点规律可以从下图看出:

     

        以上可知,只要用个递归就可实现。

        下面是实现代码:

import java.io.*;
import java.util.Scanner;
public class N_gray {

	public static void main(String[] args){
		//难道java中输入一个整数要经历很多东西吗?
		Scanner sc=new Scanner(System.in);
		String n=sc.nextLine();
		int N=Integer.parseInt(n);
	    StringBuffer[] gray_code=get_gray(N);
		for(int i=0;i<gray_code.length;i++){
			System.out.println(gray_code[i]);
		}
	}
	
	public static StringBuffer[] get_gray(int n){
		int length=(int)Math.pow(2, n);
		StringBuffer[] gray_code=new StringBuffer[length];
		if(n==1){
			gray_code[0]=new StringBuffer("0");
			gray_code[1]=new StringBuffer("1");
			
			
		}
		else{
			StringBuffer[] temp=get_gray(n-1);
		    for(int i=0;i<length;i++){
//如果用=,只是传引用,所以对gray_code[i]插值的时候会影响temp,从而导致最后的结果错误。
//gray_code[i]=temp[i%(length/2)];
		      
		    	if(i<(length/2)){
		    		gray_code[i]=new StringBuffer((temp[i]));
		        	gray_code[i].insert(0, "0");
		    	}
		        else{
		        	gray_code[i]=new StringBuffer((temp[length-i-1]));
		        	gray_code[i].insert(0, "1");

		        }
		    }
		    
		   	
		}
		return gray_code;
	}
}

格雷码还有一种实现方式是根据这个公式来的G(n) =  B(n) XOR B(n+1), 这也是格雷码和二进制码的转换公式。代码如下:

public void getGrayCode(int bitNum){
    for(int i = 0; i < (int)Math.pow(2, bitNum); i++){
        int grayCode = (i >> 1) ^ i;
        System.out.println(num2Binary(grayCode, bitNum));
    }
}
   public String num2Binary(int num, int bitNum){
    String ret = "";
    for(int i = bitNum-1; i >= 0; i--){
        ret += (num >> i) & 1;
    }
    return ret;
}


汇总:

//格雷码生成

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class GrayCode {
	private static Scanner cin;

	public List<Integer> grayCode(int n) {
		List<Integer> result = new LinkedList<>();
		if (n >= 0) {
			// 格雷码的前半部分
			result.add(0);
			// 格雷码最高位的值(非0时)
			int t = 1;
			// 每一次外循环求出的是位数i+1位的格雷码表,其相当于长度为i+1位的格雷码表的前半部分
			for (int i = 0; i < n; i++) {
				// 求出的长度为i+1位格雷码表的后半部分,前半部分由长度为i位的格雷码表给出
				for (int j = result.size() - 1; j >= 0; j--) {
					result.add(result.get(j) ^ t);
				}
				// 最高位右移
				t <<= 1;
			}
		}
		return result;
	}

	public ArrayList<Integer> grayCode2(int n) {
		ArrayList<Integer> result = new ArrayList<Integer>();
		result.add(0);
		if (n > 0) {
			result.add(1);
		}

		int mask = 1;
		for (int i = 2; i <= n; ++i) {
			mask *= 2;
			for (int j = result.size() - 1; j >= 0; --j) {
				int v = result.get(j).intValue();
				v |= mask;
				result.add(v);
			}
		}
		return result;
	}

	public void getGrayCode3(int bitNum) {
		for (int i = 0; i < (int) Math.pow(2, bitNum); i++) {
			int grayCode = (i >> 1) ^ i;
			System.out.println(num2Binary(grayCode, bitNum));
		}
	}

	public String num2Binary(int num, int bitNum) {
		String ret = "";
		for (int i = bitNum - 1; i >= 0; i--) {
			ret += (num >> i) & 1;
		}
		return ret;
	}

	public String[] GrayCode4(int n) {

		// produce 2^n grade codes
		String[] graycode = new String[(int) Math.pow(2, n)];

		if (n == 1) {
			graycode[0] = "0";
			graycode[1] = "1";
			return graycode;
		}

		String[] last = GrayCode4(n - 1);

		for (int i = 0; i < last.length; i++) {
			graycode[i] = "0" + last[i];
			graycode[graycode.length - 1 - i] = "1" + last[i];
		}

		return graycode;
	}

	public static StringBuffer[] get_gray(int n) {
		int length = (int) Math.pow(2, n);
		StringBuffer[] gray_code = new StringBuffer[length];
		if (n == 1) {
			gray_code[0] = new StringBuffer("0");
			gray_code[1] = new StringBuffer("1");

		} else {
			StringBuffer[] temp = get_gray(n - 1);
			for (int i = 0; i < length; i++) {
				// 如果用=,只是传引用,所以对gray_code[i]插值的时候会影响temp,从而导致最后的结果错误。
				// gray_code[i]=temp[i%(length/2)];

				if (i < (length / 2)) {
					gray_code[i] = new StringBuffer((temp[i]));
					gray_code[i].insert(0, "0");
				} else {
					gray_code[i] = new StringBuffer((temp[length - i - 1]));
					gray_code[i].insert(0, "1");

				}
			}

		}
		return gray_code;
	}

	public static void main(String args[]) {
		GrayCode grayCode = new GrayCode();

		cin = new Scanner(System.in);
		int n = 0;
		while (cin.hasNext()) {
			n = cin.nextInt();
			// 1.
			// System.out.println(grayCode.grayCode(n));
			// 2.
//			System.out.println(grayCode.grayCode2(n));
			// 3.
			 grayCode.getGrayCode3(n);
			// 4.
			// System.out.println(grayCode.GrayCode4(n));
			// 5.
			// for (int i = 0; i < grayCode.GrayCode4(n).length; i++) {
			// System.out.println(grayCode.GrayCode4(n)[i]);
			// }
			// 6.
			// StringBuffer[] gray_code=get_gray(n);
			// for(int i=0;i<gray_code.length;i++){
			// System.out.println(gray_code[i]);
			// }
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值