Формула Хартли
Количество информации и формула Хартли
Компьютер хранит информацию в двоичном виде — с помощью нулей и единиц. Один двоичный разряд называется битом. С помощью одного бита можно записать два различных значения:
С помощью двух бит можно записать уже четыре различные комбинации:
Каждый дополнительный бит увеличивает количество возможных комбинаций в два раза. Поэтому с помощью бит можно закодировать:
различных значений.
Алфавит и мощность алфавита
Алфавитом называют набор символов, которые могут использоваться для записи сообщения. Количество различных символов в алфавите называется его мощностью и обозначается .
Например, алфавит из десятичных цифр имеет мощность 10. Если разрешены десятичные цифры и 26 строчных латинских букв, мощность алфавита:
Если прописные и строчные буквы считаются различными символами, учитываем их отдельно:
Формула Хартли
Количество информации, приходящееся на один символ алфавита из равновероятных символов, определяется формулой Хартли:
Например, для алфавита из 32 символов:
В заданиях ЕГЭ обычно используется посимвольное кодирование: каждому символу соответствует двоичный код одинаковой длины. При этом длина кода должна быть целым числом бит.
Если мощность алфавита не является степенью двойки, результат округляют вверх:
Обозначение означает округление числа вверх до ближайшего целого.
Например, для 36 символов пяти бит недостаточно: они дают только 32 различные комбинации. Шесть бит дают 64 комбинации, поэтому их достаточно:
Использовать все 64 комбинации необязательно. Часть из них может оставаться свободной.
Объём сообщения
Если сообщение содержит символов, каждый из которых кодируется битами, его информационный объём:
Например, для пароля из 15 символов алфавита мощностью 36:
В заданиях объём памяти обычно измеряется в байтах, Кбайтах или Мбайтах:
Если для хранения каждого пароля выделяется минимальное целое число байт, его объём в байтах тоже округляют вверх:
Для рассмотренного пароля:
Одиннадцать байт содержат только 88 бит, поэтому их недостаточно.
Хранение нескольких сообщений
Если один пароль занимает байт, то для хранения таких паролей потребуется:
Например, для 100 паролей по 12 байт:
Важно соблюдать порядок действий: сначала округляем объём одного пароля до целого числа байт, затем умножаем на количество паролей. Это связано с тем, что память выделяется отдельно для каждого пароля.
Если вместе с паролем хранятся дополнительные сведения объёмом байт на пользователя, общий объём:
Отсюда объём дополнительных сведений об одном пользователе:
Обратные задачи
В задании могут попросить найти не общий объём памяти, а длину сообщения или мощность алфавита. Принцип остаётся тем же: связываем количество символов, биты на символ и выделенную память.
При составлении неравенства обращаем внимание на условие:
Если найдено количество бит на символ, важно правильно определить мощность алфавита. Для кодирования символов требуется ровно бит при условии:
Поэтому при максимальная и минимальная мощности такого алфавита:
Например, ровно 6 бит на символ требуется для алфавитов мощностью от 33 до 64.
Разбор задачи ЕГЭ
Каждой детали присваивают серийный номер, содержащий десятичные цифры, 52 латинские буквы и символы из 458-символьного специального алфавита. Все символы кодируются одинаковым и минимально возможным количеством бит. Для каждого номера выделяется минимальное целое число байт. Для хранения 862 номеров отведено не более 276 Кбайт. Найдём максимально возможную длину номера.
Сначала определим мощность алфавита:
На один символ потребуется:
так как .
Переведём доступный объём памяти в байты:
Разделим его на количество номеров. Поскольку превышать доступную память нельзя, округлим вниз:
Обозначение означает округление числа вниз до ближайшего целого.
Таким образом, один номер может занимать не более 327 байт. Переведём этот объём в биты:
Каждый символ занимает 10 бит. Следовательно, максимальная длина номера:
Решение на Python
Эту же задачу можно решить на Python, если знать две функции из библиотеки math:
ceil(x) — округляет число вверх до ближайшего целого. Например, ceil(3.2) = 4.
log2(x) — вычисляет двоичный логарифм числа. Например, log2(32) = 5, поскольку 25=32.
Для использования этих функций их нужно импортировать:
from math import ceil, log2
Теперь формулу для вычисления количества бит на символ можно записать прямо в программе:
i = ceil(log2(10 + 52 + 458))
Здесь сначала складываются мощности всех частей алфавита, затем вычисляется двоичный логарифм, а результат округляется вверх. Получаем i = 10 бит на символ.
Длина серийного номера неизвестна. Вместо её вычисления по формуле можно перебрать возможные значения и проверить каждое из них. Такой способ называется перебором, или брутфорсом.
Для этого используем цикл:
for l in range(1,10000):
Переменная l последовательно принимает значения от 1 до 9999. Для этой задачи такого диапазона достаточно: даже 1000 символов по 10 бит уже не поместятся в доступную память при указанном количестве номеров.
Для каждой длины вычисляем объём одного серийного номера в байтах:
b = ceil(l * i / 8)
Произведение l * i даёт количество бит в номере. Деление на 8 переводит биты в байты, а ceil округляет результат вверх, поскольку каждому номеру выделяется целое число байт.
Теперь проверяем, помещаются ли все номера в доступную память:
if b * 862 <= 276 * 1024:
Слева находится объём 862 номеров в байтах, справа — доступные 276 Кбайт, переведённые в байты. Знак <= соответствует словам «не более» в условии.
Если условие выполняется, сохраняем текущую длину:
maxl = l
Перебор идёт по возрастанию. Каждая следующая подходящая длина заменяет предыдущую, поэтому после завершения цикла в maxl останется максимально возможная длина.
Таким образом, получим:
from math import ceil, log2
i = ceil(log2(10 + 52 + 458))
for l in range(1,10000):
b = ceil(l * i / 8)
if b * 862 <= 276 * 1024:
maxl = l
print(maxl)Программа выводит 261. Аналогично можно решать задачи с неизвестной мощностью алфавита: тогда перебираем a, внутри цикла вычисляем i = ceil(log2(a)), а длину номера берём из условия. Если требуется минимальное значение, выводим первое подходящее и останавливаем цикл через break; если максимальное — сохраняем последнее подходящее значение, как в этой задаче.