Добавил:
hiiamfool
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:2 / main
.pyimport math
import os
import time
def calculate_entropy(data):
if not data:
return 0.0
frequency = {}
for byte in data:
frequency[byte] = frequency.get(byte, 0) + 1
entropy = 0.0
total_len = len(data)
for count in frequency.values():
p = count / total_len
if p > 0:
entropy -= p * math.log2(p)
return entropy
def get_rle_sequences(data):
if not data:
return [], 0
sequences = []
current_byte = data[0]
count = 1
max_len = 0
for b in data[1:]:
if b == current_byte:
count += 1
else:
sequences.append((current_byte, count))
if count > max_len:
max_len = count
current_byte = b
count = 1
sequences.append((current_byte, count))
if count > max_len:
max_len = count
return sequences, max_len
class BitWriter:
def __init__(self, filepath):
self.filepath = filepath
self.buffer = 0
self.bit_count = 0
self.byte_array = bytearray()
def write_bits(self, value, num_bits):
mask = (1 << num_bits) - 1
value = value & mask
self.buffer = (self.buffer << num_bits) | value
self.bit_count += num_bits
while self.bit_count >= 8:
shift = self.bit_count - 8
byte_val = (self.buffer >> shift) & 0xFF
self.byte_array.append(byte_val)
self.bit_count -= 8
mask_remainder = (1 << self.bit_count) - 1
self.buffer &= mask_remainder
def close(self):
if self.bit_count > 0:
shift = 8 - self.bit_count
byte_val = (self.buffer << shift) & 0xFF
self.byte_array.append(byte_val)
with open(self.filepath, 'wb') as f:
f.write(self.byte_array)
def main():
input_filename = 'poem.txt'
output_filename = 'poem.var1'
# 1. Чтение данных
if not os.path.exists(input_filename):
print(f"Ошибка: Файл {input_filename} не найден.")
return
with open(input_filename, 'rb') as f:
data = f.read()
# 2. Вычисление энтропии
entropy = calculate_entropy(data)
size_source_bits = len(data) * 8
start_time = time.time()
# 3. Анализ (Pass 1)
sequences, max_run_len = get_rle_sequences(data)
bits_for_length = max_run_len.bit_length()
if bits_for_length == 0: bits_for_length = 1
# 4. Кодирование (Pass 2)
writer = BitWriter(output_filename)
# Заголовок (число бит для длины)
writer.write_bits(bits_for_length, 8)
# Данные (символ + длина)
for char_byte, length in sequences:
writer.write_bits(char_byte, 8)
writer.write_bits(length, bits_for_length)
writer.close()
end_time = time.time()
compression_duration = end_time - start_time
# 5. Статистика
if os.path.exists(output_filename):
size_compressed_bytes = os.path.getsize(output_filename)
size_compressed_bits = size_compressed_bytes * 8
else:
size_compressed_bits = 0
compression_ratio = size_source_bits / size_compressed_bits if size_compressed_bits > 0 else 0
print("=== Результаты Лабораторной работы №2 (Вариант 1) ===")
print(f"Файл: {input_filename}")
print("-" * 40)
print(f"1. Энтропия Шеннона (H): {entropy:.4f} бит/символ")
print(f"2. Длина исходного текста (|S|): {size_source_bits} бит ({len(data)} байт)")
print(f"3. Максимальная длина серии: {max_run_len}")
print(f" -> Выбрано бит для хранения длины: {bits_for_length}")
print(f"4. Длина сжатого текста (|C|): {size_compressed_bits} бит ({size_compressed_bytes} байт)")
print(f"5. Коэффициент сжатия (k): {compression_ratio:.4f}")
print(f"6. Время выполнения сжатия: {compression_duration:.6f} сек")
print("-" * 40)
print(f"Сжатый файл сохранен как: {output_filename}")
if __name__ == "__main__":
main() 