C 汉明码校验奇偶校验
我不确定我是否为我编写的校验奇偶校验位函数正确计算了奇偶校验位。该码字长11个字符,有4个奇偶校验位和7个数据位。实现看起来好吗C 汉明码校验奇偶校验,c,hamming-code,C,Hamming Code,我不确定我是否为我编写的校验奇偶校验位函数正确计算了奇偶校验位。该码字长11个字符,有4个奇偶校验位和7个数据位。实现看起来好吗 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]
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';
}
实现看起来好吗
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';
}
这在很大程度上取决于你对“好”的衡量。我可以确认它确实完成了任务,所以至少它是正确的。您的代码非常冗长,因此很难检查其正确性。我会做以下几件事:
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;
}
我将整个码字视为一个整数,而不是一系列数字字符,这样效率更高
看看,我看到表中的列构成了序列1…11的二进制表示。每个码字位正好影响该列中提到的奇偶校验位,所以我取0或1的码字位,乘以该列的位模式,得到该模式或0,然后将其与当前奇偶校验位模式进行异或。其效果是零码字位不会改变任何东西,而非零码字位翻转所有相关的奇偶校验位
必须注意,因为位模式是基于一的,而使用右移技巧的位位置是基于零的。所以我必须减去一,然后右移这个量,然后提取最低有效位,以获得码字位
使用我的实现作为参考,我能够确定您的代码的工作原理是相同的。您的代码通过了我提出的测试用例,运行良好。采用了一些简化,但OP功能没有改变。为了便于查看,进行了一些经典的简化
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");
}
如果OP发布测试模式,它会很有用。这是我的实现。它起作用了。公众可以免费使用它 我使用了首字母缩略词secded作为in,单错误纠正,双错误检测。如果需要,可以将其重新连接为三重错误检测器。事实上,这其中的一小部分是保密的,其余的是汉明7,4-但我把这些方法命名为我所做的,当我做的时候 这里的字符串不是NUL终止的,而是计数的。这段代码摘自用C编写的Python模块。这就是您看到的字符串类型的来源 这里的一个关键点是认识到只有16个汉明7,4码。我用一些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;
}
为什么不使用位字段?我将替换Dopopy= InPulfDouLe2,i用TopopWar=1 @ RangeNoDy,而不是做码字[2 ] -48 +码字[4 ] -48 +…,考虑码字[2 ] -48 ^码字[4 ] -48 ^。那么如果奇偶校验[i]%2==0。。。不需要。此外,-48 s/b-'0'。如果奇偶校验[i]%2..4行if语句。。可以替换为更有效的奇偶校验[i]&=1;。我猜@means matters的意思是“位域”,即使用位移位操作将单个整数视为位序列。这是非常便携的,请参见我的答案以获取示例。不可移植的是作为structelements的位字段,也就是说,对结构的一个成员使用少于一个完整的可寻址字节。双重错误检测需要全局奇偶校验位,这在原始问题的版本中没有提到。此外,问题是实现Hamming11,7,而不是Hamming7,4,因此有128个有效的码字。总的来说,我看不出你的实现对回答这个问题有什么帮助。啊,你是对的,这是汉明7,4+奇偶校验。对不起,你不能进去。一个128个码字的数组显然不需要创建或存储空间。感谢有机会澄清这些挑剔之处。