简体   繁体   English

汉明码校验奇偶校验

[英]Hamming code check parity

I am not sure if I am calculating the parity bit correctly for the the check Parity bit function I wrote. 我不确定我是否为我编写的check Parity bit函数正确计算了奇偶校验位。 The codeWord is 11 chars long with 4 parity bits and 7 data bits. codeWord的长度为11个字符,具有4个奇偶校验位和7个数据位。 Does the implementation look good? 实现看起来不错吗?

void parityCheck(char* codeWord) {
int parity[4] = {0}, i = 0, diffParity[4] = {0}, twoPower = 0, bitSum = 0;

// Stores # of 1's for each parity bit in array.
parity[0] = (codeWord[2] - 48) + (codeWord[4] - 48) + (codeWord[6] - 48) + (codeWord[8] - 48) + (codeWord[10] - 48);
parity[1] = (codeWord[2] - 48) + (codeWord[5] - 48) + (codeWord[6] - 48) + (codeWord[9] - 48) + (codeWord[10] - 48);
parity[2] = (codeWord[4] - 48) + (codeWord[5] - 48) + (codeWord[6] - 48);
parity[3] = (codeWord[8] - 48) + (codeWord[9] - 48) + (codeWord[10] - 48);

// Determines if sum of bits is even or odd, then tests for difference from actual parity bit.
for (i = 0; i < 4; i++) {
    twoPower = (int)pow((double)2, i);

    if (parity[i] % 2 == 0)
            parity[i] = 0;
        else
            parity[i] = 1;

        if ((codeWord[twoPower-1] - 48) != parity[i])
            diffParity[i] = 1;
}

// Calculates the location of the error bit.
for (i = 0; i < 4; i++) {
    twoPower = (int)pow((double)2, i);
    bitSum += diffParity[i]*twoPower;
}



// Inverts bit at location of error.
if (bitSum <= 11 && bitSum > 0) {
    if ((codeWord[bitSum-1] - 48)) 
        codeWord[bitSum-1] = '0';
    else
        codeWord[bitSum-1] = '1';
}

Does the implementation look good? 实现看起来不错吗?

This very much depends on your measure for “good”. 这在很大程度上取决于您对“良好”的衡量。 I can confirm that it does get the job done, so at least it is correct. 我可以确认它确实可以完成工作,因此至少是正确的。 Your code is very verbose, and thus hard to check for correctness. 您的代码非常冗长,因此很难检查其正确性。 I'd do the following: 我将执行以下操作:

int parity_check(int codeWord) {
  int parity = 0, codeWordBit, bitPos;
  for (bitPos = 1; bitPos <= 11; ++bitPos) {
    codeWordBit = ((codeWord >> (bitPos - 1)) & 1);
    parity ^= bitPos*codeWordBit;
  }
  if (parity != 0) {
    if (parity > 11)
      return -1; // multi-bit error!
    codeWord ^= 1 << (parity - 1);
  }
  return codeWord;
}

Instead of a sequence of digit characters, I treat your whole code word as a single integer, which is a lot more efficient. 我将整个代码字视为一个整数,而不是数字字符序列,这样效率更高得多。

Looking at the table at Wikipedia , I see that the columns of that table form binary representations of the sequence 1 … 11. Each code word bit affects exactly those parity bits mentioned in that column, so I take the code word bit (which is zero or one), multiply it by the bit pattern of that column to obtain either that pattern or zero, then XOR this with the current parity bit pattern. 查阅Wikipedia的表 ,我看到该表的构成了序列1…11的二进制表示。每个代码字位正好影响该列中提到的那些奇偶校验位,因此我将代码字位(为零)或一个),将其乘以该列的位模式以获得该模式或零,然后将其与当前奇偶校验位模式进行异或。 The effect of this is that a zero code word bit won't change anything, whereas a non-zero code word bit flips all associated parity bits. 这样的结果是零代码字位不会改变任何东西,而非零代码字位会翻转所有关联的奇偶校验位。

Some care has to be taken because the bit pattern is one-based, whereas the bit position using the right shift trick is zero-based. 由于位模式是从1开始的,而使用右移技巧的位位置是从0开始的,因此必须小心。 So I have to subtract one, then shift right by that amount, and then extract the least significant digit in order to obtain the codeWordBit . 因此,我必须减去一个,然后向右移该数量,然后提取最低有效数字,以获得codeWordBit

Using my implementation for reference, I was able to verify (by complete enumeration) that your code works the same. 使用我的实现作为参考,我能够(通过完整的枚举)验证您的代码是否工作相同。

Your code works fine AFAIK as it passed test cases I conjured up. 您的代码通过了我构想的测试用例后,在AFAIK上运行良好。 Some simplifications were employed, but the OP functionality not changed. 进行了一些简化,但OP功能未更改。 Some classic simplifications were made for easier viewing. 进行了一些经典的简化,以便于查看。

void parityCheck(char* cW) {
  int parity[4] = { 0 }, i = 0, diffParity[4] = { 0 }, twoPower = 0, bitSum = 0;

  // Stores # of 1's for each parity bit in array.
  parity[0] = (cW[2] - '0') + (cW[4] - '0') + (cW[6] - '0') + (cW[8] - '0') + (cW[10] - '0');
  parity[1] = (cW[2] - '0') + (cW[5] - '0') + (cW[6] - '0') + (cW[9] - '0') + (cW[10] - '0');
  parity[2] = (cW[4] - '0') + (cW[5] - '0') + (cW[6] - '0');
  parity[3] = (cW[8] - '0') + (cW[9] - '0') + (cW[10] - '0');

  // Determines if sum of bits is even or odd, then tests for difference from actual parity bit.
  for (i = 0; i < 4; i++) {
    //twoPower = (int) pow((double) 2, i);
    twoPower = 1 << i;
    //if (parity[i] % 2 == 0) parity[i] = 0; else parity[i] = 1;
    parity[i] &= 1;  // Make 0 even, 1 odd.
    if ((cW[twoPower - 1]-'0') != parity[i])
      diffParity[i] = 1;
  }

  // Calculates the location of the error bit.
  for (i = 0; i < 4; i++) {
    // twoPower = (int) pow((double) 2, i);
    twoPower = 1 << i;
    bitSum += diffParity[i] * twoPower;
  }

  // Inverts bit at location of error.
  if (bitSum <= 11 && bitSum > 0) {
    if ((cW[bitSum - 1]-'0')) 
      cW[bitSum - 1] = '0';
    else
      cW[bitSum - 1] = '1';
  }
}

void TestP(const char * Test) {
  char buf[100];
  strcpy(buf, Test);
  parityCheck(buf);
  printf("'%s' '%s'\n", Test, buf);
}


int main(void) {
  TestP("00000000000");
  TestP("10011100101");
  TestP("10100111001");
}

It would have been useful had the OP posted test patterns. 如果OP发布了测试模式,这将很有用。

Here's my implementation. 这是我的实现。 It works. 有用。 The public is free to use it at no charge. 公众可以免费免费使用它。

I used the acronym "secded" as in, "single-error-correcting, double-error-detecting." 我在“单错误纠正,双错误检测”中使用了缩写“ secded”。 You can re-wire this as a "triple error detector" if you want that instead. 如果需要,可以将其重新连接为“三重错误检测器”。 Really, some small part of this is secded and the rest is Hamming 7,4 -- but I named these methods what I did, when I did. 确实,其中的一小部分已被拆分,其余的是汉明7,4-但是我将这些方法命名为我所做的工作。

The "strings" here are not NUL-terminated, but counted. 这里的“字符串”不是以NUL结尾的,而是计算在内。 This code is excerpted from a Python module written in C. That is the provenance of the string type you see. 这段代码摘自用C语言编写的Python模块。这就是您看到的字符串类型的来源。

A key point here was realizing that there are only 16 Hamming 7,4 codes. 这里的关键是要意识到只有16个汉明7,4码。 I calculated secded_of_nibble() with some Python code, which unfortunately I no longer have. 我用一些Python代码计算了secded_of_nibble(),不幸的是我不再拥有了。

static const unsigned char secded_of_nibble[] = 
{ 0x0, 0xd2, 0x55, 0x87, 0x99, 0x4b, 0xcc, 0x1e, 0xe1, 0x33, 0xb4, 0x66, 0x78, 0
xaa, 0x2d, 0xff };

int fec_secded_encode_cch_bits(const char * strIn, const int cchIn, char * strOu
t, const int cchOut)
{
    assert( cchIn * 2 == cchOut);
    if( cchIn * 2 != cchOut)
        return 0;

    if (!strIn || !strOut)
        return 0;

    int i;
    for (i = 0; i < cchIn; i ++)
    {
        char in_byte = strIn[i];
        char hi_byte = secded_of_nibble[(in_byte >> 4) & 0xf];
        char lo_byte = secded_of_nibble[in_byte & 0xf];

        strOut[i * 2] = hi_byte;
        strOut[i * 2 + 1] = lo_byte;
    }

    return 1;
}

char bv_H[] = {0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8};

char val_nibble(char ch)
{
    return ((ch & 0x20) >> 2) | ((ch & 0xE) >> 1);
}

char correct_nibble(char ch)
{
    char nibble = 0;
    int i = 0;
    for (i = 0; i < 8; i++)
    if (ch & (1 << (7-i)))
        nibble ^= bv_H[i];

    return nibble;
}

void apply_correct(char nib_correct, char * pbyte, int * pcSec, int *pcDed)
{
    if (0 == nib_correct)
        return;

    if (nib_correct & 0x8)
    {
        (*pcSec) ++;

        int bit = (8 - (nib_correct & 0x7)) & 0x7;
        /*  fprintf(stderr, "bit %d, %02X\n", bit, 1 << bit);*/
        (*pbyte) ^= (1 << bit);
    }
    else
    {
        (*pcDed) ++;
    }
}

int fec_secded_decode_cch_bits
(
    const char * strIn, 
    const int cchIn, 
    char * strOut, 
    const int cchOut,
    int * pcSec,
    int * pcDed
)
{
    assert( cchIn == cchOut *2);
    if( cchIn != cchOut * 2)
        return 0;

    if (!strIn || !strOut)
        return 0;

    int i;
    for (i = 0; i < cchOut; i ++)
    {
        char hi_byte = strIn[i * 2];
        char lo_byte = strIn[i * 2 + 1];


        char hi_correct = correct_nibble(hi_byte);
        char lo_correct = correct_nibble(lo_byte);

        if (hi_correct || lo_correct)
        {
            apply_correct(hi_correct, &hi_byte, pcSec, pcDed);
            apply_correct(lo_correct, &lo_byte, pcSec, pcDed);
/*          fprintf(stderr, "Corrections %x %x.\n", hi_correct, lo_correct);*/
        }

        char hi_nibble = val_nibble(hi_byte);
        char lo_nibble = val_nibble(lo_byte);

        strOut[i] = (hi_nibble << 4) | lo_nibble;
    }

    return 1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM