使用Hamming(7,4)纠正错误


19

Hamming(7,4)代码可以追溯到1950年。当时,Richard Hamming在贝尔实验室担任数学家。汉明每个星期五都设置计算机进行一系列计算,并在下周一收集结果。使用奇偶校验,这些机器能够在计算过程中检测到错误。沮丧,因为他经常收到错误消息,所以汉明决定改进错误检测并发现了著名的汉明代码。

海明力学(7,4)

汉明码的目的是创建一组重叠的奇偶校验位,以便可以检测和纠正数据位或奇偶校验位中的单个错误(翻转一位)。仅当发生多个错误时,汉明码才能恢复原始数据。它可能根本不会注意到错误,甚至可能会错误地纠正它。因此,在这一挑战中,我们将仅处理单位错误。

作为汉明代码的示例,我们将看一下汉明(7,4)代码。除4位数据外,d1, d2, d3, d4它还使用3个奇偶校验位p1, p2, p3,这些奇偶校验位使用以下公式计算:

p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2

产生的代码字(数据+奇偶校验位)的格式为p1 p2 d1 p3 d2 d3 d4

检测错误的方法如下。您重新计算奇偶校验位,并检查它们是否与接收的奇偶校验位匹配。在下表中,您可以看到,各种单一位错误都会产生奇偶校验位的不同匹配。因此,可以定位和纠正每个单位错误。

error in bit | p1 | p2 | d1 | p3 | d2 | d3 | d4 | no error
-------------|---------------------------------------------
p1 matches   | no | yes| no | yes| no | yes| no | yes
p2 matches   | yes| no | no | yes| yes| no | no | yes
p3 matches   | yes| yes| yes| no | no | no | no | yes

让您的数据成为1011。奇偶校验位是p1 = 1 + 0 + 1 = 0p2 = 1 + 1 + 1 = 1p3 = 0 + 1 + 1 = 0。组合数据和奇偶校验位,您将得到码字0110011

data bits   |   1 011
parity bits | 01 0
--------------------
codeword    | 0110011

假设在传输或计算过程中第6位(=第3数据位)翻转。您会收到这个词0110001。据称收到的数据是1001。您重新计算奇偶校验位p1 = 1 + 0 + 1 = 0p2 = 1 + 0 + 1 = 0p3 = 0 + 0 + 1 = 1。仅p1匹配代码字的奇偶校验位0110001。因此发生错误。查看上表,告诉我们发生了错误d3,您可以恢复原始数据1011

挑战:

编写一个接收一个字(7位)的函数或程序,其中一位可能是错误的,然后恢复原始数据。输入(通过STDIN,命令行参数,提示或函数参数)格式可以是MSB中的字符串"0110001",列表或数组[0, 1, 1, 0, 0, 0, 1]或整数0b0110001 = 49。如上所述,输入的顺序为p1 p2 d1 p3 d2 d3 d4。输出(通过返回值或STDOUT)必须具有相同的格式,但顺序为d1 d2 d3 d4。仅返回/输出4个数据位。

这是代码高尔夫球。因此,以最短的代码为准。

测试用例:

1110000 -> 1000  # no error
1100000 -> 1000  # error at 1st data bit
1111011 -> 1111  # error at 2nd data bit
0110001 -> 1011  # error at 3rd data bit (example)
1011011 -> 1010  # error at 4th data bit
0101001 -> 0001  # error at 1st parity bit
1010000 -> 1000  # error at 2nd parity bit
0100010 -> 0010  # error at 3rd parity bit


1
是否有特定原因会在第一个数据位之后给出最后一个奇偶校验位?
xnor

2
@xnor从数学上讲,奇偶校验位在什么位置没有什么区别。从历史上看,它们被置于两个权力的位置。例如汉明(15,11)具有在位置1,2,4和8的奇偶校验位
Jakube

4
@xnor如果采用[is_p3_wrong][is_p2_wrong][is_p1_wrong]基数2,则会给出单词中错误位的位置。(基于问题的表格。)这对于某些算法可能很有用。
randomra 2015年

非常好:)当您编写“写一个接收到一个单词(7位)的函数或程序时,其中之一可能是错误的,[...]”我想您是说其中一位可能是错误的,但是您实际上说的话可能是其中之一。

@Lembik当然可以了。
Jakube 2015年

Answers:


6

八度,70 66 55字节

此功能用于F设置解码矩阵H,查找错误并更正错误的位置(如果存在)。然后它返回正确的数据位。输入是标准行向量。

@Jakube建议,我应该使用Octave而不是Matlab,在这里可以在表达式上使用索引,这会使整个过程再缩短11个字节:

F=@(c)xor(c,1:7==bi2de(mod(c*de2bi(1:7,3),2)))([3,5:7])

以下是Matlab中最短的解决方案,因为您不能直接在表达式上使用索引。(当然,这也可以在Octave中使用。)能够用xor:替换additional / mod2 :

f=@(c)c([3,5:7]);F=@(c)f(xor(c,1:7==bi2de(mod(c*de2bi(1:7,3),2))))

旧:

f=@(c)c([3,5:7]);F=@(c)f(mod(c+(1:7==bi2de(mod(c*de2bi(1:7,3),2))),2))

谢谢,但是这行不通,不幸的是,您只能以这种方式访问​​变量...
更加糟糕的

1
没有安装Matlab,我只http://octave-online.net/在能工作的地方使用过。也许改变语言?
2015年

哦,我已经很怀疑八度可以这样做了,但是我当然会改变语言,非常感谢!
flawr

14

彼得50x11 = 550

在此处输入图片说明

Codel的大小为15。不太担心大小,但是它通过了所有测试。


4
考虑到问题的背景,我宁愿这样。

1
@Optimizer的“ codel大小”本质上是piet程序的放大系数。此处,每个逻辑像素(或编码1)已扩展为15x15的块,以使可见性更容易。那是我的意思,而不是“代码大小”
captncraig 2015年

啊.....我的坏。
Optimizer

8

Python,79岁

f=lambda x,n=0,e=3:e&~-e and f(x,n+1,(n&8)*14^(n&4)*19^(n&2)*21^n%2*105^x)or~-n

将输入和输出视为数字,右边的最低有效位。

与其尝试进行错误恢复,不如尝试将每个可能的消息n从0 编码为15,直到获得的编码与给出的编码相差一小部分。递归一直递增,n直到找到有效的递归并返回为止。尽管没有显式终止,但它必须在16个循环内结束。

该表达式(n&8)*14^(n&4)*19^(n&2)*21^n%2*105按位实现汉明矩阵。

为了检查单个错误,我们将给定的消息与计算得到的消息进行异或运算e,然后使用经典的bit-trick检查它是否是2的幂(或0)e&~-e==0。但是,我们实际上无法e在lambda中分配该变量,因此我们在此表达式中两次对其进行了引用,因此我们很想将其作为可选参数传递给下一个递归步骤。


7

JavaScript(ES6),92 87 81

函数在MSB中获取和返回一个整数。
在@randomra注释之后,实现是Straightforwrd:

  • calc p3wrong | p2wrong | p1wrong(第2、3、4行)
  • 将其用作位掩码以翻转错误的位(第1行),
  • 然后只返回数据位(最后一行)
F=w=>(w^=128>>(
  (w^w*2^w*4^w/2)&4|
  (w/8^w^w*2^w/16)&2|
  (w/16^w/4^w^w/64)&1
))&7|w/2&8

测试在Frefox /萤火控制台

;[0b1110000,0b1100000,0b1111011,0b0110001,
0b1011011,0b0101001,0b1010000,0b0100010]
.map(x=>x.toString(2)+'->'+F(x).toString(2))

输出量

["1110000->1000", "1100000->1000", "1111011->1111", "110001->1011", "1011011->1010", "101001->1", "1010000->1000", "100010->10"]

1
我真的很喜欢您的紧凑按位操作解决方案=)
瑕疵的

4

Python 2,71

f=lambda i,b=3:i&7|i/2&8if chr(i)in'\0%*3<CLUZfip'else f(i^b/2,b*2)

几个字符是不可打印的ASCII,因此这是转义的版本:

f=lambda i,b=3:i&7|i/2&8if chr(i)in'\0\x0f\x16\x19%*3<CLUZfip\x7f'else f(i^b/2,b*2)

函数的输入和输出以整数形式完成。

我利用了这样一个事实,即有效消息的数量仅为16,并对所有消息进行硬编码。然后,我尝试翻转不同的位,直到得到其中之一。


3

Haskell,152个字节

a(p,q,d,r,e,f,g)=b$(d+e)#p+2*(d+f)#q+4*(e+f)#r where b 3=(1-d,e,f,g);b 5=(d,1-e,f,g);b 6=(d,e,1-f,g);b 7=(d,e,f,g-1);b _=(d,e,f,g);x#y=abs$(x+g)`mod`2-y

用法:a (1,1,1,1,0,1,1)输出哪个(1,1,1,1)

简单的解决方案:如果p<x>不匹配,则<x>在数字中设置位。如果这个数字是356或者7,翻转对应d<y>


您是否可以添加更多有关如何调用代码的说明(例如,使用诸如ideone.com之类的在线编译器)?我总是会遇到一些奇怪的错误(很可能是我的错)。
2015年

@Jakube:将代码保存到文件中,然后说说hamming.hs并加载到Haskell REPL ghci:中ghci hamming.hsa如上所述调用函数。唯一的网上哈斯克尔解释我所知道的(tryhaskell.org)需要一些更多的代码:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
NIMI

3

IA-32机器代码,36个字节

十六进制转储:

33 c0 40 91 a8 55 7a 02 d0 e1 a8 66 7a 03 c0 e1
02 a8 78 7a 03 c1 e1 04 d0 e9 32 c1 24 74 04 04
c0 e8 03 c3

等效的C代码:

unsigned parity(unsigned x)
{
    if (x == 0)
        return 0;
    else
        return x & 1 ^ parity(x >> 1);
}

unsigned fix(unsigned x)
{
    unsigned e1, e2, e3, err_pos, data;
    e1 = parity(x & 0x55);
    e2 = parity(x & 0x66);
    e3 = parity(x & 0x78);
    err_pos = e1 + e2 * 2 + e3 * 4;
    x ^= 1 << err_pos >> 1;
    data = x;
    data &= 0x74;
    data += 4;
    data >>= 3;
    return data;
}

x86 CPU自动计算每个中间结果的奇偶校验。它具有专用指令jp,该指令根据奇偶校验来跳转或不跳转。

挑战中没有明确指定它,但是汉明码的便利属性是您可以将奇偶校验位解释为二进制数,并且该数字指示在传输过程中损坏了哪个位。实际上,该数字是从1开始的,0表示没有传输错误。这是通过将1向左移动err_pos然后向右移动来实现的1

纠正传输错误后,代码按所需顺序排列数据位。该代码针对大小进行了优化,起初可能不清楚其工作方式。来解释它,我表示由abcd的数据比特,并且通过PQ并且R所述奇偶校验位。然后:

    data = x;     // d  c  b  R  a  Q  P
    data &= 0x74; // d  c  b  0  a  0  0
    data += 4;    // d  c  b  a ~a  0  0
    data >>= 3;   // d  c  b  a

汇编源(fastcall约定,输入在中ecx,输出在中eax):

    xor eax, eax;
    inc eax;
    xchg eax, ecx;

    test al, 0x55;
    jp skip1;
    shl cl, 1;

skip1:
    test al, 0x66;
    jp skip2;
    shl cl, 2;

skip2:
    test al, 0x78;
    jp skip3;
    shl ecx, 4;

skip3:
    shr cl, 1;
    xor al, cl;

    and al, 0x74;
    add al, 4;
    shr al, 3;

    ret;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.