Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2 / main

.py
Скачиваний:
0
Добавлен:
27.12.2025
Размер:
4.57 Кб
Скачать
import 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()
Соседние файлы в папке 2