오류 검출 방식 비교 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""오류 검출 방식 비교 문서의 주장 검증: 같은 오류 패턴을 패리티, 2차원 패리티, 체크섬, CRC-16에 넣어 본다."""
import random
def bits_of(data):
return [(b >> (7 - i)) & 1 for b in data for i in range(8)]
def parity_ok(data, p):
return sum(bits_of(data)) % 2 == p
def two_d(data):
rows = [sum((b >> i) & 1 for i in range(8)) % 2 for b in data]
col = 0
for b in data:
col ^= b
return rows, col
def checksum(data):
words = [(data[i] << 8) | (data[i + 1] if i + 1 < len(data) else 0) for i in range(0, len(data), 2)]
s = 0
for w in words:
s += w; s = (s & 0xFFFF) + (s >> 16)
return ~s & 0xFFFF
def crc16(data, poly=0x8005):
"""CRC-16 (다항식 x^16 + x^15 + x^2 + 1)."""
r = 0
for b in data:
r ^= b << 8
for _ in range(8):
r = ((r << 1) ^ poly) & 0xFFFF if r & 0x8000 else (r << 1) & 0xFFFF
return r
def flip(data, positions):
d = list(data)
for p in positions:
d[p // 8] ^= 1 << (7 - p % 8)
return d
def main():
random.seed(51)
n = 32; trials = 4000
miss = {"parity": 0, "2d": 0, "checksum": 0, "crc16": 0}
for k in (2, 4):
for _ in range(trials):
data = [random.randrange(256) for _ in range(n)]
pos = random.sample(range(8 * n), k)
bad = flip(data, pos)
if sum(bits_of(bad)) % 2 == sum(bits_of(data)) % 2: miss["parity"] += 1
if two_d(bad) == two_d(data): miss["2d"] += 1
if checksum(bad) == checksum(data): miss["checksum"] += 1
if crc16(bad) == crc16(data): miss["crc16"] += 1
print("놓친 수 (2·4비트 오류 각 4000번):", miss)
assert miss["parity"] == 2 * trials # 짝수 개 오류는 한 번도 못 찾는다
assert miss == {"parity": 8000, "2d": 0, "checksum": 132, "crc16": 0}
# 버스트 오류(연속 16비트 안): CRC-16은 모두 검출
for _ in range(3000):
data = [random.randrange(256) for _ in range(n)]
L = random.randint(1, 16); s = random.randint(0, 8 * n - L)
pos = [s] + [s + i for i in range(1, L - 1) if random.random() < 0.5] + ([s + L - 1] if L > 1 else [])
assert crc16(flip(data, pos)) != crc16(data)
# 체크섬이 놓치는 짝: 같은 열 자리의 두 비트가 0→1, 1→0으로 서로 상쇄
data = [0x00, 0x01, 0x00, 0x00] # 워드 0x0001, 0x0000
bad = [0x00, 0x00, 0x00, 0x01] # 워드 0x0000, 0x0001
assert checksum(bad) == checksum(data) and crc16(bad) != crc16(data)
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()