校验码(海明校验,CRC冗余校验,奇偶校验)
循环冗余校验码
CRC码利用生成多项式为k个数据位产生r个校验位进行编码,其编码长度为n=k+r所以又称 (n,k)码. CRC码广泛应用于数据通信领域和磁介质存储系统中. CRC理论非常复杂,一般书就给个例题,讲讲方法.现在简单介绍下它的原理:
在k位信息码后接r位校验码,对于一个给定的(n,k)码。可以证明(数学高手自己琢磨证明过程)存在一个最高次幂为 n-k=r 的多项式g(x),根据g(x)可以生成k位信息的校验码,g(x)被称为 生成多项式
用C(x)=C(k-1)C(k-2)...C0表示k个信息位,把C(x)左移r位,就是相当于 C(x)*pow(2,r) 给校验位空出r个位来了.给定一个 生成多项式g(x),可以求出一个校验位表达式r(x) 。C(x)*pow(2,r) / g(x) = q(x) + r(x)/g(x) 用C(x)*pow(2,r)去除生成多项式g(x)商为q(x)余数是r(x)。所以有C(x)*pow(2,r) = q(x)*g(x) + r(x)。
C(x)*pow(2,r) + r(x)就是所求的n位CRC码,由上式可以看出它是生成多项式g(x)的倍式.所以如果用得到的n位CRC码去除g(x)如果余数是0,就证明数据正确. 否则可以根据余数知道出错位.
在CRC运算过程中,四则运算采用 mod 2运算(后面介绍),即不考虑进位和借位. 所以上式等价于C(x)*pow(2,r) + r(x) = q(x)*g(x)
继续前先说下基本概念吧.
1.多项式和二进制编码
x的最高次幂位对应二进制数的最高位.以下各位对应多项式的各幂次. 有此幂次项为1,无为0. x的最高幂次为r时, 对应的二进制数有r+1位 例如g(x)=pow(x,4) + pow(x,3) + x + 1 对应二进制编码是 11011
2.生成多项式是发送方和接受方的一个约定,也是一个二进制数,在整个传输过程中,这个数不会变.
在发送方利用 生成多项式 对信息多项式做模2运算生成校验码.
在接受方利用 生成多项式 对收到的 编码多项式 做模2运算校验和纠错.
生成多项式应满足:
a.生成多项式的最高位和最低位必须为1
b.当信息任何一位发生错误时,被生成多项式模2运算后应该使余数不为0
c.不同位发生错误时,应该使余数不同.
d.对余数继续做模2除,应使余数循环.
生成多项式很复杂,不过不用我们生成。
下面给出一些常用的生成多项式表
n k 二进制码(自己根据多项式和二进制编码 的介绍转)
7 4 1011 或 1101
7 3 11011 或 10111
15 11 1011
31 26 100101
3.模2运算
a.加减法法则
0 +/- 0 = 0
0 +/- 1 = 1
1 +/- 0 = 1
1 +/- 1 = 0
注意:没有进位和借位
b.乘法法则
利用模2加求部分积之和,没有进位
c.除法法则
利用模2减求部分余数,没有借位,每商1位则部分余数减1位,余数最高位是1就商1,不是就商0,当部分余数的位数小于余数时,该余数就是最后余数.
例 1110
1011)1100000
1011
1110
1011
1010
1011
0010(每商1位则部分余数减1位,所以前两个0写出)
0000
010(当部分余数的位数小于余数时,该余数就是最后余数)
最后商是1110余数是010
好了说了那么多没用的理论.下面讲下CRC的实际应用.例: 给定的生成多项式g(x)=1011, 用(7,4)CRC码对C(x)=1010进行编码.
由题目可以知道下列的信息:
C(x)=1010,n=7,k=4,r=3,g(x)=1011 C(x)*pow(2,3)=1010000 C(x)*pow(2,3) / g(x) = 1001 + 11/1011 所以r(x)=011.所以要求的编码为1010011
例2: 上题中,数据传输后变为1000011,试用纠错机制纠错. 1000011 / g(x) = 1011 + 110/1011
不能整除,所以出错了. 因为余数是110.查1011出错位表可以知道是第5位出错.对其求反即可.
冗余码的计算方法是,先将信息码后面补0,补0的个数是生成多项式最高次幂;将补零之后的信息码除以G(X),注意除法过程中所用的减法是模2减法,即没有借位的减法,也就是异或运算。当被除数逐位除完时,得到比除数少一位的余数。此余数即为冗余位,将其添加在信息位后便构成CRC码字。
例如,假设信息码字为11100011,生成多项式G(X)=X^5+X^4+X+1,计算CRC码字。
G(X) = X^5+X^4+X+1,也就是110011,因为最高次是5,所以,在信息码字后补5个0,变为1110001100000。用1110001100000除以110011,余数为11010,即为所求的冗余位。
因此发送出去的CRC码字为原始码字11100011末尾加上冗余位11010,即 1110001111010。接收端收到码字后,采用同样的方法验证,即将收到的码字除以G(X),发现余数是0,则认为码字在传输过程中没有出错。
package com.hjzgg.crc; import java.util.ArrayList; public class CrcCheck {
/*
CRC-4 x4+x+1 3 ITU G.704
CRC-8 x8+x5+x4+1 0x31
CRC-8 x8+x2+x1+1 0x07
CRC-8 x8+x6+x4+x3+x2+x1 0x5E
CRC-12 x12+x11+x3+x+1 80F
CRC-16 x16+x15+x2+1 8005 IBM SDLC
CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
CRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
CRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP
*/
public static final String[] polynomeMsg = {"CRC-4 : x4+x+1", "CRC-8 : x8+x5+x4+1", "CRC-8 : x8+x2+x1+1",
"CRC-8 : x8+x6+x4+x3+x2+x1", "CRC-12 : x12+x11+x3+x+1", "CRC-16 : x16+x15+x2+1", "CRC16-CCITT : x16+x12+x5+1",
"CRC-32 : x32+x26+x23+...+x2+x+1", "CRC-32c : x32+x28+x27+...+x8+x6+1"};
private final int bits[] = {4,8,8,8,12,16,16,32,32};
private int polynomeChoose = 0;
private String msg = null; public String getMsg(){
return msg;
} public int getPolynomeChoose() {
return polynomeChoose;
} public void setPolynomeChoose(int polynomeChoose) {
this.polynomeChoose = polynomeChoose;
} private static final int[] polynome = {0x3, 0x31, 0x07, 0x5E, 0x80F, 0x8005, 0x1021, 0x04C11DB7, 0x1EDC6F41}; public void toCrcCode(ArrayList<Integer> code){
msg = "信息源码: ";
for(int i=0; i<code.size(); ++i)
msg += code.get(i);
int poly = polynome[polynomeChoose];//选择的多项式
int r = bits[polynomeChoose]-1;//多项式的位数
for(int i=1; i<=r; ++i)//将原信息扩大 r-1 位,用来填充校验码
code.add(0);
int crc = 0;//余数
int highBit = 1<<r;//获取crc的最高位
poly |= highBit;
for(int i=0; i<code.size(); ++i){
crc |= code.get(i);
if((crc&highBit) != 0)//最高位如果是1,则进行模2运算,即异或运算
crc ^= poly;
crc <<= 1;
}
crc>>=1;
while(r > 0){
code.set(code.size()-r, (crc&(1<<(r-1)))==0 ? 0 : 1);
--r;
}
msg += ", CRC校验码: ";
for(int i=0; i<code.size(); ++i)
msg += code.get(i);
} public boolean crcCheck(ArrayList<Integer> code){
msg += ", 接收到信息码: ";
int poly = polynome[polynomeChoose];//选择的多项式
int r = (int)(Math.log(poly)/Math.log(2) + 0.5)+1;//多项式的位数
int crc = 0;//余数
int highBit = 1<<r;//获取crc的最高位
poly |= highBit;
for(int i=0; i<code.size(); ++i){
msg += code.get(i);
crc |= code.get(i);
if((crc&highBit) != 0)//最高位如果是1,则进行模2运算,即异或运算
crc ^= poly;
crc <<= 1;
}
crc>>=1;
if(crc == 0){
msg += ", 校验结果: 0, 正确!";
return true;
}
else{
msg += ", 校验结果: " + Integer.toBinaryString(crc) + ", 出错!";
return false;
}
} public static void main(String[] args) {
int cd[]={1,0,1,1,0,0,1};
ArrayList<Integer> code = new ArrayList<Integer>();
for(int i=0; i<cd.length; ++i)
code.add(cd[i]);
new CrcCheck().toCrcCode(code);
}
}
奇偶校验码
奇偶校验码最简单,但只能检测出奇数位出错. 如果发生偶数位错误就无法检测. 但经研究是奇数位发生错误的概率大很多. 而且奇偶校验码无法检测出哪位出错.所以属于无法矫正错误的校验码。奇偶校验码是奇校验码和偶校验码的统称. 它们都是通过在要校验的编码上加一位校验位组成. 如果是奇校验加上校验位后,编码中1的个数为奇数个。如果是偶校验加上校验位后,编码中1的个数为偶数个。
例:
原编码 奇校验 偶校验
0000 0000 1 0000 0
0010 0010 0 0010 1
1100 1100 1 1100 0
1010 1010 1 1010 0
如果发生奇数个位传输出错,那么编码中1的个数就会发生变化. 从而校验出错误,要求从新传输数据。目前应用的奇偶校验码有3种.
水平奇偶校验码对每一个数据的编码添加校验位,使信息位与校验位处于同一行.
垂直奇偶校验码把数据分成若干组,一组数据排成一行,再加一行校验码. 针对每一行列采用奇校验 或 偶校验
例: 有32位数据10100101 00110110 11001100 10101011
垂直奇校验 垂直偶校验
10100101 10100101 数据
00110110 00110110
11001100 11001100
10101011 10101011
00001011 11110100 校验
水平垂直奇偶校验码就是同时用水平校验和垂直校验
例:
奇校验奇水平 偶校验 偶水平
10100101 1 10100101 0 数据
00110110 1 00110110 0
11001100 1 11001100 0
10101011 0 10101011 1
00001011 0 11110100 1 校验
package com.hjzgg.even_odd_check; import java.util.ArrayList; public class EvenOddCheck {
private final boolean EVEN_CHECK = true;
private final boolean ODD_CHECK = false; private boolean flag = ODD_CHECK; private String msg = null; public String getMsg(){
return msg;
} public void setEvenCheck(){
flag = EVEN_CHECK;
} public void setOddCheck(){
flag = ODD_CHECK;
} public void toEvenOddCode(ArrayList<Integer> code){
msg = "信息源码: ";
for(int i=0; i<code.size(); ++i)
msg += code.get(i);
int cnt1 = 0;//数字1的个数
for(int i=0; i<code.size(); ++i)
if(code.get(i) == 1)
++cnt1;
if(flag == EVEN_CHECK){
if((cnt1&1) == 1)
code.add(0, 1);
else code.add(0, 0);
} else if(flag == ODD_CHECK){
if((cnt1&1) == 1)
code.add(0, 0);
else code.add(0, 1);
}
msg += ", 奇偶校验码: ";
for(int i=0; i<code.size(); ++i)
msg += code.get(i);
} public boolean evenOddCheck(ArrayList<Integer> code){
msg += ", 接收到信息码: ";
int cnt1 = 0;//数字1的个数
for(int i=0; i<code.size(); ++i){
msg += code.get(i);
if(code.get(i) == 1)
++cnt1;
}
if((cnt1&1)==1 && flag == ODD_CHECK || (cnt1&1)==0 && flag==EVEN_CHECK){
msg += ", 校验结果: 正确!";
return true;
} else {
msg += ", 校验结果: 错误!";
return false;
}
} public static void main(String[] args) { } }
海明验码
海明码也是利用奇偶性来校验数据的. 它是一种多重奇偶校验检错系统,它通过在数据位之间插入k个校验位,来扩大码距,从而实现检错和纠错.
设原来数据有n位,要加入k位校验码.怎么确定k的大小呢? k个校验位可以有pow(2,k) (代表2的k次方) 个编码,其中有一个代表是否出错. 剩下pow(2,k)-1个编码则用来表示到底是哪一位出错. 因为n个数据位和k个校验位都可能出错,所以k满足pow(2,k)-1 >= n+k。
设 k个校验码为 P1,P2...Pk, n个数据位为D0,D1...Dn 产生的海明码为 H1,H2...H(n+k) 。如有8个数据位,根据pow(2,k)-1 >= n+k可以知道k最小是4。那么得到的海明码是:
H12 H11 H10 H9 H8 H7 H6 H5 H4 H3 H2 H1
D7 D6 D5 D4 P4 D3 D2 D1 P3 D0 P2 P1
然后怎么知道Pi校验哪个位呢. 自己可以列个校验关系表
海明码 下标 校验位组
H1(P1) 1 P1
H2(P2) 2 P2
H3(D0) 1+2 P1,P2
H4(P3) 4 P3
H5(D1) 1+4 P1,P2
H6(D2) 2+4 P2,P3
H7(D3) 1+2+4 P1,P2,P3
H8(P4) 8 P4
H9(D4) 1+8 P1,P4
H10(D5) 2+8 P2,P4
H11(D6) 1+2+8 P1,P2,P4
H12(D7) 4+8 P3,P4
从表中可以看出
P1校验 P1,D0,D1,D3,D4,D6
P2校验 P2,D0,D1,D2,D3,D5,D6
P3校验 P3,D2,D3,D7
P4校验 P4,D4,D5,D6,D7
其实上表很有规律很容易记,要知道海明码Hi由哪些校验组校验,可以把i化成二进制数数中哪些位k是1,就有哪些Pk校验
如H7 7=0111 所以由P1,P2,P3 H11 11=1011 所以由P1,P2,P4 H3 3=0011 所以由P1,P2
那看看Pi的值怎么确定,如果使用偶校验,则
P1=D0 xor D1 xor D3 xor D4 xor D6
P2=D0 xor D1 xor D2 xor D3 xor D5 xor D6
P3=D1 xor D2 xor D3 xor D7
P4=D4 xor D5 xor D6 xor D7
其中xor是异或运算,奇校验的话把偶校验的值取反即可.那怎么校验错误呢. 其实也很简单. 先做下面运算.
G1 = P1 xor D0 xor D1 xor D3 xor D4 xor D6
G2 = P2 xor D0 xor D1 xor D2 xor D3 xor D5 xor D6
G3 = P3 xor D1 xor D2 xor D3 xor D7
G4 = P4 xor D4 xor D5 xor D6 xor D7
package com.hjzgg.hammingcheck; import java.util.ArrayList;
import java.util.Collections; public class HammingCheck { private String msg = null; public String getMsg(){
return msg;
} private int checkNumber_k(int n){
int kk = (int)(Math.log(n)/Math.log(2) + 0.5);
for(int k=kk; ; ++k)
if(n+k <= (int)(Math.pow(2.0, (double)k)+0.5)-1)
return k;
} public void toHammingCode(ArrayList<Integer> code){
msg = "信息源码: ";
for(int i=0; i<code.size(); ++i)
msg += code.get(i);
Collections.reverse(code);//海明码的编码是从右到左,由小到大的
int n = code.size();
int k = checkNumber_k(n);
int index = 1;
for(int i=1; i<=k; ++i){//插入校验位
code.add(index-1, 0);
index<<=1;
}
//校验位取值
for(int i=0; i<code.size(); ++i){
if(((i+1)&i) != 0){//如果这一位不是校验位,也就是数据位
int x = i+1;//表示该有效数据是位于串中的几位
int p_index = 1;//校验位的索引
while(x != 0){
if((x&1) == 1)
code.set(p_index-1, code.get(p_index-1)^code.get(i));
x>>=1;
p_index<<=1;//下一个校验位的索引
}
}
}
Collections.reverse(code);
msg += ", 海明校验码: ";
for(int i=0; i<code.size(); ++i)
msg += code.get(i);
} public boolean hammingCheck(ArrayList<Integer> code){
msg += ", 接收到信息码: ";
Collections.reverse(code);
ArrayList<Integer> s = new ArrayList<Integer>();//校验的结果值
int k=1;
while(k <= code.size()){//si的每一位初值为校验位pi的值
s.add(code.get(k-1));
k<<=1;
}
for(int i=0; i<code.size(); ++i){
if(((i+1)&i) != 0){//如果这一位不是校验位,也就是数据位
int x = i+1;//表示该有效数据是位于串中的第几位
int p_index = 1;//校验位的索引
while(x != 0){
if((x&1) == 1){
int s_index = (int)(Math.log(p_index)/Math.log(2.0) + 0.5)+1;//通过校验位找到 对应的校验结果s的索引
s.set(s_index-1, s.get(s_index-1)^code.get(i));
}
x>>=1;
p_index<<=1;//下一个校验位的索引
}
}
}
Collections.reverse(code);
int ret = 0;
int radix = 1;
for(int i=0; i<s.size(); ++i){
ret += s.get(i)*radix;
radix<<=1;
}
if(ret == 0){
msg += ", 校验结果: 正确!";
return true;
}
else {
Collections.reverse(s);
msg += ", 校验结果: " + s + ", 第" + ret + "位出错!";
return false;
}
} public static void main(String[] args) {
int cd[]={1,0,1,0};
ArrayList<Integer> code = new ArrayList<Integer>();
for(int i=0; i<cd.length; ++i)
code.add(cd[i]);
HammingCheck hc = new HammingCheck();
hc.toHammingCode(code);
System.out.println("海明码: " + code);
//假设cdd中的是接受到的信息,然后利用海明码纠错检验
int cdd[]={1, 0, 1, 0, 0, 1, 1};
code.clear();
for(int i=0; i<cdd.length; ++i)
code.add(cdd[i]);
hc.hammingCheck(code);
} }
执行程序部分:
package com.hjzgg.thread; import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap; import javax.swing.JOptionPane; import com.hjzgg.frame.MainFrame; public class MyThread implements Runnable{
private String xxxCode;
private MainFrame mainFrame;
private static final Map<String,Integer> mp = new TreeMap<String, Integer>();
static{
mp.put("HammingCode", 5210);
mp.put("CrcCode", 5211);
mp.put("EvenOddCode", 5212);
}
public MyThread(MainFrame mainFrame, String xxxCode){
this.mainFrame = mainFrame;
this.xxxCode = xxxCode;
}
@Override
public void run() {
ServerSocket server=null;
Socket socket=null;
BufferedReader is = null;
if(mp.get(xxxCode) == null) return;
try{
server = new ServerSocket(mp.get(xxxCode));
while(true){
socket = server.accept();
is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String codeText = is.readLine();
ArrayList<Integer> code = new ArrayList<Integer>();
for(int i=0; i<codeText.length(); ++i)
code.add(Integer.parseInt(""+codeText.charAt(i)));
if("HammingCode".equals(xxxCode)){
mainFrame.getHc().hammingCheck(code);
JOptionPane.showMessageDialog(null, mainFrame.getHc().getMsg(), "海明校验结果", JOptionPane.INFORMATION_MESSAGE);
} else if("CrcCode".equals(xxxCode)){
mainFrame.getCc().crcCheck(code);
JOptionPane.showMessageDialog(null, mainFrame.getCc().getMsg(), "CRC校验结果", JOptionPane.INFORMATION_MESSAGE);
} else {
mainFrame.getEoc().evenOddCheck(code);
JOptionPane.showMessageDialog(null, mainFrame.getEoc().getMsg(), "奇偶校验结果", JOptionPane.INFORMATION_MESSAGE);
}
}
} catch(Exception e){
System.out.println("Error:" + e.toString());
} finally {
try{
if(is != null)
is.close(); //关闭Socket输入流
if(socket != null)
socket.close(); //关闭Socket
if(server != null)
server.close(); //关闭ServerSocket
} catch (Exception e){
System.out.println("Error:" + e.toString());
}
}
}
}
package com.hjzgg.frame; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Random; import com.hjzgg.crc.CrcCheck;
import com.hjzgg.even_odd_check.EvenOddCheck;
import com.hjzgg.hammingcheck.HammingCheck; public class MyActionListener implements ActionListener{
private MainFrame mainFrame;
public MyActionListener(MainFrame mainFrame){
this.mainFrame = mainFrame;
}
private void myRandom(ArrayList<Integer> code){
Random random = new Random();
if(random.nextInt()%2 == 0){//出错
int index = Math.abs(random.nextInt())%code.size();
code.set(index, code.get(index)^1);
}
}
public void actionPerformed(ActionEvent e) {
String codeText = mainFrame.getCodeText().getText();
ArrayList<Integer> code = new ArrayList<Integer>();
for(int i=0; i<codeText.length(); ++i)
code.add(Integer.parseInt(""+codeText.charAt(i)));
if(e.getActionCommand().equals("hammingBtn")){
try{
Socket socket=new Socket("127.0.0.1", 5210);
PrintWriter os=new PrintWriter(socket.getOutputStream());
mainFrame.getHc().toHammingCode(code);
myRandom(code);
codeText = "";
for(int i=0; i<code.size(); ++i)
codeText += code.get(i);
os.print(codeText);
os.flush();
socket.close(); //关闭Socket
}catch(Exception ex) {
System.out.println("Error:"+ex); //出错,则打印出错信息
}
} else if(e.getActionCommand().equals("crcBtn")){
try{
Socket socket=new Socket("127.0.0.1", 5211);
PrintWriter os=new PrintWriter(socket.getOutputStream());
mainFrame.getCc().toCrcCode(code);
myRandom(code);
codeText = "";
for(int i=0; i<code.size(); ++i)
codeText += code.get(i);
os.print(codeText);
os.flush();
socket.close(); //关闭Socket
}catch(Exception ex) {
System.out.println("Error:"+ex); //出错,则打印出错信息
}
} else {
try{
Socket socket=new Socket("127.0.0.1", 5212);
PrintWriter os=new PrintWriter(socket.getOutputStream());
mainFrame.getEoc().toEvenOddCode(code);
myRandom(code);
codeText = "";
for(int i=0; i<code.size(); ++i)
codeText += code.get(i);
os.print(codeText);
os.flush();
socket.close(); //关闭Socket
}catch(Exception ex) {
System.out.println("Error:"+ex); //出错,则打印出错信息
}
}
}
}
主程序:
package com.hjzgg.frame; import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.HeadlessException;
import java.awt.TextField; import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel; import com.hjzgg.crc.CrcCheck;
import com.hjzgg.even_odd_check.EvenOddCheck;
import com.hjzgg.hammingcheck.HammingCheck;
import com.hjzgg.thread.MyThread; public class MainFrame extends JFrame{
private TextField codeText;//传输的信息码
private HammingCheck hc = new HammingCheck();
private EvenOddCheck eoc = new EvenOddCheck();
private CrcCheck cc = new CrcCheck(); public HammingCheck getHc() {
return hc;
} public EvenOddCheck getEoc() {
return eoc;
} public CrcCheck getCc() {
return cc;
} public TextField getCodeText() {
return codeText;
} private JButton crcBtn = new JButton("CRC冗余校验");
private JButton hammingBtn = new JButton("海明校验");
private JButton evenOddBtn = new JButton("奇偶校验");
private JComboBox evenOddComboBox=new JComboBox();
private JComboBox crcComboBox=new JComboBox();
private JComboBox hammingComboBox=new JComboBox();
private void init(){
JPanel topPanel = new JPanel(), downPanel = new JPanel();
topPanel.setPreferredSize(new Dimension(400, 80));
topPanel.setBackground(Color.blue);
add(topPanel, BorderLayout.NORTH);
downPanel.setPreferredSize(new Dimension(400, 180));
downPanel.setBackground(Color.green);
add(downPanel, BorderLayout.SOUTH); FlowLayout topFlowLayout = new FlowLayout();
topFlowLayout.setAlignment(FlowLayout.CENTER);
topFlowLayout.setVgap(20);
topPanel.setLayout(topFlowLayout);
JLabel label = new JLabel("信息码:");
label.setForeground(Color.red);
topPanel.add(label);
codeText = new TextField(50);
topPanel.add(codeText); FlowLayout downFlowLayout = new FlowLayout();
downFlowLayout.setHgap(10);
downPanel.setLayout(downFlowLayout);
JPanel evenOddPanel = new JPanel(), crcPanel = new JPanel(), hammingPanel = new JPanel();
evenOddPanel.setPreferredSize(new Dimension(90, 150));
crcPanel.setPreferredSize(new Dimension(350, 150));
hammingPanel.setPreferredSize(new Dimension(90, 150));
downPanel.add(evenOddPanel);
downPanel.add(crcPanel);
downPanel.add(hammingPanel); evenOddPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 30));
crcPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 30));
hammingPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 30));
for(int i=0; i<CrcCheck.polynomeMsg.length; ++i)
crcComboBox.addItem(CrcCheck.polynomeMsg[i]);
evenOddComboBox.addItem("奇校验");
evenOddComboBox.addItem("偶校验");
hammingComboBox.addItem("好看而已");
crcPanel.add(crcComboBox);
evenOddPanel.add(evenOddComboBox);
hammingPanel.add(hammingComboBox);
evenOddPanel.add(evenOddBtn);
crcPanel.add(crcBtn);
hammingPanel.add(hammingBtn); MyActionListener mcl = new MyActionListener(this);
evenOddBtn.addActionListener(mcl);
evenOddBtn.setActionCommand("evenOddBtn");
crcBtn.addActionListener(mcl);
crcBtn.setActionCommand("crcBtn");
hammingBtn.addActionListener(mcl);
hammingBtn.setActionCommand("hammingBtn");
setBounds(50, 100, 600, 300);
setVisible(true);
} public MainFrame() throws HeadlessException {
super();
init();
} public MainFrame(String title) throws HeadlessException {
super(title);
init();
} public static void main(String[] args) {
// TODO Auto-generated method stub
MainFrame mainFrame = new MainFrame();
{//开启服务端,准备接受信息码
// "HammingCode"
// "CrcCode"
// "EvenOddCode"
new Thread(new MyThread(mainFrame,"HammingCode")).start();
new Thread(new MyThread(mainFrame,"CrcCode")).start();
new Thread(new MyThread(mainFrame,"EvenOddCode")).start();
} } }
实验结果: 有图有真相!
理论摘自:http://blog.sina.com.cn/s/blog_03f18e5e0100r25y.html
校验码(海明校验,CRC冗余校验,奇偶校验)的更多相关文章
- 海明码 CRC冗余校验码
海明码(也叫汉明码)具有一位纠错能力.本文以1010110这个二进制数为例解释海明码的编码和校验方法 确定校验码的位数x 设数据有n位,校验码有x位.则校验码一共有2x种取值方式.其中需要一种取值方式 ...
- CRC冗余校验码的介绍和实现
from:http://yoyo.play175.com/p/200.html 节选至百度百科: 首先,任何一个由二进制数位串组成的代码,都可以惟一地与一个只含有0和1两个系数的多项式建立一一对应的关 ...
- CRC 冗余校验计算
(1)设G(x)为r阶,则在信息位末尾加r个0形成新信息 r=原信息位数 - 1
- 常用校验码(奇偶校验码、海明校验码、CRC校验码)
一.奇偶校验码 二.海明校验码 三.CRC校验码 计算机系统运行时,各个部之间要进行数据交换.交换的过程中,会有发生误码的可能(即0变成1或1变成0),由于计算机的储存是通过二进制代码来实现的的, ...
- [技术栈]CRC校验原理及C#代码实现CRC16、CRC32计算FCS校验码
1.CRC.FCS是什么 CRC,全称Cyclic Redundancy Check,中文名称为循环冗余校验,是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检 ...
- 汉明码、海明校验码(Hamming Code)
目录 基础知识 汉明码/海明校验码 计算 基础知识 码距:又叫海明距离,是在信息编码中,两个编码之间对应位上编码不同的位数.例如编码100110和010101,第1.2.5.6位都不相同,所以这两个编 ...
- Hamming校验码
可参考:http://winda.blog.51cto.com/55153/1068000 Hamming校验码作用:用于校验通信数据,防止出现错误,并具有一定的纠错功能. 汉明码在传输的消息流中插入 ...
- 常用校验码(奇偶校验,海明校验,CRC)学习总结
常用校验码(奇偶校验,海明校验,CRC)学习总结 一.为什么要有校验码? 因为在数据存取和传送的过程中,由于元器件或者噪音的干扰等原因会出现错误,这个时候我们就需要采取相应的措施,发现并纠正错误,对于 ...
- CRC校验码原理、实例、手动计算
目录一.CRC16实现代码二.CRC32编码字符表三.CRC校验码的手动计算示例四.CRC校验原理五.CRC的生成多项式参考 一.CRC16实现代码 思路:取一个字符(8bit),逐位检查该字符,如果 ...
随机推荐
- placeholder js简单实现
window.onload = function() { var input = document.getElementById("input"); input.onblur = ...
- 第三周作业(一):安装VS以及创建单元测试
安装的时候找的是最新版本的VS2015,因为不想花钱也不想用破解版,所以用社区版本. 下了一个IOS文件,社区版VS2015,个人免费版,强行表示不用盗版来表现自己高尚的情操:D 放入虚拟光驱软件后, ...
- Sublime Text 3实用快捷键大全
下面是我通过网上教程和文本资料学习sublime Text3时收集的一些实用功能和常用快捷键,现在分享出来,如果还有其它的好用的功能可以在下面留言,以便互相学习和交流,谢谢!. 选择类 Ctrl+ ...
- 续关于C#的微信开发的入门记录一
前几天写了一篇博客<关于C#的微信开发的入门记录一>,原文地址:http://www.cnblogs.com/zhankui/p/4515905.html,现在继续完善: 目前很多小伙伴都 ...
- ajax的理解与工作流程
一.什么是ajax ajax是一种异步通信技术.在ajax出现之前,客户端与服务端之间直接通信.引入ajax之后,客户端与服务端加了一个第三者--ajax.有了ajax之后,通过在后台与服务器进行少量 ...
- >hibernate初认识
一.什么是hibernate 1.hibernate是java领域的一款开源的ORM框架技术 2.hibernate对JDBC进行了非常轻量级的封装(使用了反射机制+配置或注解) 二.hibernat ...
- yii笔一----基础,安装,结构,增删改查基本操作
从yii中文站开始http://www.yiichina.com/ Yii 是一个高性能,基于组件的 PHP 框架 一. 1.安装yii方式 composer安装或者下载一份应用程序模板.刚开始学习, ...
- wamp2.5 局域网无法访问问题
1.打开http.conf文件,在对应处修改为如下内容(通常经过步骤一之后就能访问了,若不行则再执行后面步骤) <Directory /> Options FollowSymLinks A ...
- 关于[super dealloc]
销毁一个对象时,需要重写系统的dealloc方法来释放当前类所拥有的对象,在dealloc方法中需要先释放当前类中所有的对象,然后再调用[super dealloc]释放父类中所拥有的对象.如先调用[ ...
- android——HttpUrlConnection
前面了解了下服务端和客户端的相关知识 ,那么他们是通过什么来进行进行连接的呢? Android可以用HttpURLConnection或HttpClient接口来开发http程序.在Android 上 ...