1 / 11

Кодирование по Фано

a. b. c. d. e. f. g. h. i. j. k. 20. 18. 17. 11. 10. 7. 5. 4. 4. 3. 1. 0. a. b. c. 1. d. e. f. g. h. i. j. k. 55. 20. 18. 17. 45. 11. 10. 7. 5. 4. 4. 3. 1. 00. a. 01. b. c. 10. d. e. 11. f. g. h. i. j. k. 20. 35. 18. 17. 21. 11.

petula
Télécharger la présentation

Кодирование по Фано

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. a b c d e f g h i j k 20 18 17 11 10 7 5 4 4 3 1 0 a b c 1 d e f g h i j k 55 20 18 17 45 11 10 7 5 4 4 3 1 00 a 01 b c 10 d e 11 f g h i j k 20 35 18 17 21 11 10 24 7 5 4 4 3 1 e f g h i j k d b a c 101 1100 1101 11100 11101 11110 11111 00 100 011 010 Кодирование по Фано

  2. Программа на языке Java public class Code { public long code; // Собственно код символа public byte len; // Длина кода // Символы (в порядке убывания вероятностей появления) public static char[] chars = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}; // Вероятности появления символов public static int[] probs = { 20, 18, 17, 11, 10, 7, 5, 4, 4, 3, 1 }; // Формируемый массив кодов public static Code[] codes = new Code[chars.length]; }

  3. public class Fano { private static int mediana(int low, int high) { int sLow = 0; // Сумма первых элементов int sHigh = Code.probs[high]; // Сумма последних элементов for (int i = low; i < high; i++) { sLow += Code.probs[i]; } int m = high; // Перед поиском границы sLow = sum[low:(high-1)], sHigh = sum[high] int diff; do { m--; diff = Math.abs(sLow - sHigh); // Вычисляем предыдущую разность // Изменяем верхнюю и нижнюю суммы sLow -= Code.probs[m]; sHigh += Code.probs[m]; } while (Math.abs(sLow - sHigh) < diff); // Цикл заканчивается, когда разности перестанут уменьшаться return m; } public static void fano(int low, int high) { if (low < high) { // Определяем границу равных сумм вероятностей int m = mediana(low, high); for (int i = low; i <= high; i++) { // Сдвигаем коды и дописываем нули в первую половину и единицы во вторую Code.codes[i].code <<= 1; if (i > m) Code.codes[i].code++; Code.codes[i].len++; } // Рекурсивный вызов алгоритма для двух отдельных половин таблицы fano(low, m); fano(m+1, high); } } }

  4. bcdfijk a a a a a a a a b b b b b b b c c c c c c bc c bc d d d d d d e e e e e f f f f g g g h h h i i j k 61 20 20 20 20 20 20 20 20 18 18 18 18 18 18 18 17 17 35 17 35 17 17 17 17 11 11 11 11 11 11 10 10 10 10 10 7 7 7 7 5 5 5 4 4 4 4 4 3 1 aegh aegh dfijk dfijk dfijk egh egh egh fijk fijk gh gh ijk ijk jk 39 39 26 26 26 19 19 19 15 15 9 9 8 8 4 Кодирование по Хаффмену

  5. a 10 aegh 1 e 110 g 1110 egh 11 gh 111 h 1111 b 000 bc 00 i 01000 c 001 ijk 0100 bcdfijk 0 j 010000 fijk 010 jk 01000 dfijk 01 k 010001 f 0101 d 011

  6. public class Huffman { // Рабочая копия массива вероятностей static int[] prs = new int[Code.probs.length]; private static int up(int n, int p) { int j = n-1; // Поиск начинаем с конца таблицы while (j >= 1) { if (prs[j-1] < p) { // Сдвиг по таблице prs[j] = prs[j-1]; j--; } else { // Место в таблице найдено break; } } // Вставка значения в таблицу и возврат prs[j] = p; return j; } public static void huffman(int n) { if (n == 2) { // Предельный случай - два символа в таблице Code.codes[0] = new Code((long)0, (byte)1); Code.codes[1] = new Code((long)1, (byte)1); } else { // Просуммируем две наименьшие вероятности и вставим в табицу на свое место int j = up(n, prs[n-2] + prs[n-1]); // Рекурсивный вызов алгоритма для уменьшенной таблицы huffman(n-1); // Приписывание кодов согласно сохраненному значению j down(n, j); } }

  7. private static void down(int n, int j) { Code c = new Code(Code.codes[j]); // Запомнили код for (int i = j; i < n-2; i++) { // Сдвигаем коды вниз по таблице Code.codes[i].assign(Code.codes[i+1]); } // Восстанавливаем два последних кода c.len++; c.code <<= 1; Code.codes[n-2] = new Code(c); c.code++; Code.codes[n-1] = new Code(c); } }

  8. Некоторые сведения из модульной арифметики • a  b (mod n)  a mod n = b mod n • Операции «по модулю n»: a +n b  (a + b) mod na *n b  (a * b) mod n • Малая теорема Ферма: 0 < a < p  ap-1  1 (mod p) • Следствие из «китайской теоремы об остатках»:n = p*q и x  y (mod n)  x  y (mod p) и x  y (mod q)

  9. Шифрование с открытым ключом • Выбираем два простых числа pи q; • Вычисляем n = p*q; • Выбираем нечетное e, взаимно простое с (p-1)(q-1); • Вычисляем d = e–1 mod (p-1)(q-1); • Открытый ключ – пара <n, e>;Закрытый ключ – пара <n, d>. • Исходное сообщение: S = S0S1…Sk,Шифрованное сообщение: C = C0C1…Ck. • Шифрование: Ci = (Si)e mod n;Расшифровка: Pi = (Ci)d mod n. • Утверждение: Pi = Si.

  10. Доказательство корректности • Pi = (Si)ed mod n. Покажем, что при M < n Med M mod n • Это очевидно верно при M = 0 • При M > 0 по малой теореме Ферма:Med = M (Mp-1)k(q-1), поскольку ed = 1 + k(p-1)(q-1);Med  M  1k(q-1)  M (mod p) • Аналогично, Med  M (mod q),следовательно, Med  M (mod n)

  11. Пример кода • Выберем p = 3, q = 11. • Тогда n = 33, (p-1)(q-1) = 20, • Выберем e = 7, тогда d = 3 (ed = 21; 21  1 mod 20) • Фрагменты сообщения могут быть не длиннее 5 бит. • Пусть S0 = 21, S1 = 13, S2 = 17Тогда C0 = 217 mod 33 = 21, C1 = 137 mod 33 = 7, C2 = 177 mod 33 = 8, • Проверка (расшифровка):P0 = 213 mod 33 = 21 = S0,P1 = 73 mod 33 = 13 = S1,P2 = 83 mod 33 = 17 = S2,

More Related