-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHammingEncoder.cs
More file actions
148 lines (126 loc) · 7.33 KB
/
HammingEncoder.cs
File metadata and controls
148 lines (126 loc) · 7.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using HammingChecker;
public class HammingEncoder : IHammingStrategy
{
// & 1 - отримання найменшого біта 0001
public byte[] Encode(byte[] bytes)
{
// Створюємо список для зберігання закодованих байтів.
List<byte> encodedBytes = new();
// Проходимо кожний байт вхідних даних.
foreach (byte b in bytes)
{
// Розбиваємо кожний байт на окремі біти.
int[] bits = new int[8];
for (int i = 0; i < 8; i++)
{
bits[i] = (b >> i) & 1;
}
// Створюємо масив для зберігання закодованих бітів.
int[] encodedBits = new int[12];
// Розміщуємо біти даних на відповідних позиціях в закодованому слові.
encodedBits[2] = bits[0];
encodedBits[4] = bits[1];
encodedBits[5] = bits[2];
encodedBits[6] = bits[3];
encodedBits[8] = bits[4];
encodedBits[9] = bits[5];
encodedBits[10] = bits[6];
encodedBits[11] = bits[7];
// Обчислюємо біти парності.
encodedBits[0] = encodedBits[2] ^ encodedBits[4] ^ encodedBits[6] ^ encodedBits[8] ^ encodedBits[10];
encodedBits[1] = encodedBits[2] ^ encodedBits[5] ^ encodedBits[6] ^ encodedBits[9] ^ encodedBits[10];
encodedBits[3] = encodedBits[4] ^ encodedBits[5] ^ encodedBits[6] ^ encodedBits[11];
encodedBits[7] = encodedBits[8] ^ encodedBits[9] ^ encodedBits[10] ^ encodedBits[11];
// Конвертуємо закодовані біти назад у байти.
byte encodedByte1 = (byte)(encodedBits[0] | (encodedBits[1] << 1) | (encodedBits[2] << 2) | (encodedBits[3] << 3) | (encodedBits[4] << 4) | (encodedBits[5] << 5) | (encodedBits[6] << 6) | (encodedBits[7] << 7));
byte encodedByte2 = (byte)(encodedBits[8] | (encodedBits[9] << 1) | (encodedBits[10] << 2) | (encodedBits[11] << 3));
// Додаємо закодовані байти до списку.
encodedBytes.Add(encodedByte1);
encodedBytes.Add(encodedByte2);
}
// Повертаємо закодовані байти як масив.
return encodedBytes.ToArray();
}
public byte[] Decode(byte[] bytes)
{
// Створюємо список для зберігання декодованих байтів.
List<byte> decodedBytes = new();
// Проходимо кожний байт вхідних даних.
for (int i = 0; i < bytes.Length; i += 2)
{
// Розбиваємо кожний байт на окремі біти.
int[] encodedBits = new int[12];
for (int j = 0; j < 8; j++)
{
encodedBits[j] = (bytes[i] >> j) & 1;
}
for (int j = 0; j < 4; j++)
{
encodedBits[j + 8] = (bytes[i + 1] >> j) & 1;
}
// Обчислюємо біти парності.
int[] parityBits = new int[4];
parityBits[0] = encodedBits[0] ^ encodedBits[2] ^ encodedBits[4] ^ encodedBits[6] ^ encodedBits[8] ^ encodedBits[10];
parityBits[1] = encodedBits[1] ^ encodedBits[2] ^ encodedBits[5] ^ encodedBits[6] ^ encodedBits[9] ^ encodedBits[10];
parityBits[2] = encodedBits[3] ^ encodedBits[4] ^ encodedBits[5] ^ encodedBits[6] ^ encodedBits[11];
parityBits[3] = encodedBits[7] ^ encodedBits[8] ^ encodedBits[9] ^ encodedBits[10] ^ encodedBits[11];
// Визначаємо позицію помилки.
int errorBit = parityBits[0] | (parityBits[1] << 1) | (parityBits[2] << 2) | (parityBits[3] << 3);
if (errorBit != 0)
{
// Виправляємо помилку, змінюючи біт на вказаній позиції.
encodedBits[errorBit - 1] ^= 1;
}
// Конвертуємо закодовані біти назад у байти.
byte decodedByte = (byte)(encodedBits[2] | (encodedBits[4] << 1) | (encodedBits[5] << 2) | (encodedBits[6] << 3) | (encodedBits[8] << 4) | (encodedBits[9] << 5) | (encodedBits[10] << 6) | (encodedBits[11] << 7));
// Додаємо декодований байт до списку.
decodedBytes.Add(decodedByte);
}
// Повертаємо декодовані байти як масив.
return decodedBytes.ToArray();
}
public byte[] IntroduceError(byte[] bytes, int errorPosition)
{
// Визначте індекс байта та біта в межах масиву байтів.
int byteIndex = errorPosition / 8;
int bitIndex = 7 - (errorPosition % 8);
// Вносимо помилку в байт, змінюючи біт на вказаній позиції.
// Використовуємо операцію XOR з маскою, яка має 1 на відповідній позиції.
bytes[byteIndex] ^= (byte)(1 << bitIndex);
return bytes;
}
public byte[] DetectAndCorrectError(byte[] bytes)
{
// Проходимо через кожний байт у масиві.
for (int i = 0; i < bytes.Length; i += 2)
{
// Розбиваємо кожний байт на окремі біти.
int[] encodedBits = new int[12];
for (int j = 0; j < 8; j++)
{
encodedBits[j] = (bytes[i] >> j) & 1;
}
for (int j = 0; j < 4; j++)
{
encodedBits[j + 8] = (bytes[i + 1] >> j) & 1;
}
// Обчислюємо біти парності.
int[] parityBits = new int[4];
parityBits[0] = encodedBits[0] ^ encodedBits[2] ^ encodedBits[4] ^ encodedBits[6] ^ encodedBits[8] ^ encodedBits[10];
parityBits[1] = encodedBits[1] ^ encodedBits[2] ^ encodedBits[5] ^ encodedBits[6] ^ encodedBits[9] ^ encodedBits[10];
parityBits[2] = encodedBits[3] ^ encodedBits[4] ^ encodedBits[5] ^ encodedBits[6] ^ encodedBits[11];
parityBits[3] = encodedBits[7] ^ encodedBits[8] ^ encodedBits[9] ^ encodedBits[10] ^ encodedBits[11];
// Визначаємо позицію помилки.
int errorBit = parityBits[0] | (parityBits[1] << 1) | (parityBits[2] << 2) | (parityBits[3] << 3);
if (errorBit != 0)
{
// Виправляємо помилку, змінюючи біт на вказаній позиції.
encodedBits[errorBit - 1] ^= 1;
}
// Записуємо виправлені біти назад у масив байтів.
bytes[i] = (byte)(encodedBits[0] | (encodedBits[1] << 1) | (encodedBits[2] << 2) | (encodedBits[3] << 3) | (encodedBits[4] << 4) | (encodedBits[5] << 5) | (encodedBits[6] << 6) | (encodedBits[7] << 7));
bytes[i + 1] = (byte)(encodedBits[8] | (encodedBits[9] << 1) | (encodedBits[10] << 2) | (encodedBits[11] << 3));
}
return bytes;
}
}