Автор: Пользователь скрыл имя, 02 Апреля 2013 в 19:38, курсовая работа
В данном курсовом проекте были программно реализованы теоретические знания, полученные в течение всего семестра. Были рассмотрены методы нахождения энтропии зависимых и независимых систем, основные способы кодирования информации. В частности были реализованы методы кодирования Шеннона-Фано и кодирование по Хаффману. Реализованы были также основные методы помехоустойчивого кодирования, коды с обнаружением одиночной ошибки, коды с обнаружение и возможностью исправления одиночной ошибки. Рассмотрены способы шифрования входных сообщений, такие как метод шифрования со смещением, и RSA.
Введение…………………………………………………………………………2
Глава 1. Информационные характеристики дискретных
случайных величин…………………………………………………....4
1.1 Задание………….……………………………………………………………4
1.2 Теория………….…………………………………………………………….4
1.3 Программная реализация и алгоритмы…………………………………….5
1.3.1 Запуск программы, входные и выходные данные………………………..5
1.3.2 Алгоритмы и функции……………………………………………………...5
1.3.3 Тестирование………………………………………………………………..7
Глава 2. Оптимальное кодирование……………………………………………..8
2.1 Задание………………………………………………………………………...8
2.2 Теория…………………………………………………………………………8
2.3 Программная реализация и алгоритмы…………………………………….10
2.3.1 Запуск программы, входные и выходные данные .……………………...10
2.3.2 Алгоритмы и функции…………………………………………………….10
2.3.3 Тестирование………………………………………………………………16
Глава 3. Помехоустойчивое кодирование………………...……………………19
3.1 Задание……………………………………………………………………….19
3.2 Теория………………………………………………………………………...19
3.3 Программная реализация и алгоритмы…………………………………….23
3.3.1 Запуск программы, входные и выходные данные .……………………...23
3.3.2 Алгоритмы и функции…………………………………………………….23
3.3.3 Тестирование………………………………………………………………27
Глава 4. Шифрование данных…….…………………………………………….27
4.1 Задание……………………………………………………………………….27
4.2 Теория………………………………………………………………………...27
4.3 Программная реализация и алгоритмы…………………………………….30
4.3.1 Запуск программы, входные и выходные данные .……………………...30
4.3.2 Алгоритмы и функции…………………………………………………….30
4.3.3 Тестирование………………………………………………………………34
5. Заключение……………………………………………………………………35
Приложение 1……………………………………………………………………36
Приложение 2……………………………………………………………………37
Приложение 3……………………………………………………………………41
Приложение 4……………………………………………………………………43
Кодирование по Хаффману.
Еще одним
способом построения оптимальных кодов
является метод Хаффмана. Буквы
располагаются в порядке
После этого выполняют приписывание компонентам составных букв символов 0 и 1: первой букве всегда приписывают 0, а второй -1.
Ниже показан пример кодирования по Хаффману:
a |
0,3142 |
c-d |
0,4 |
a-b |
0,6 |
ab-cd |
1 |
||
b |
0,2857 |
а |
0,3146 |
c-d |
0,4 |
||||
c |
0,2 |
b |
0,2857 |
||||||
d |
0,2 |
||||||||
ab-cd |
ab |
0 |
cd |
1 |
a |
00 | |||
cd |
1 |
a |
00 |
b |
01 | ||||
b |
01 |
c |
10 | ||||||
d |
11 |
Формула для нахождения средней длины кода :
Формула для нахождения избыточности:
(1-H/n)*100%
2.3
Программная реализация и
2.3.1 Запуск программы, входные и выходные данные.
Для запуска программы необходимо кликнуть на файл названием tik_lab2.exe, после этого откроется консольное окно с кодами, закодированными и декодированными сообщениями.
Для изменения исходных данных нужно открыть файл lab2.cpp и изменить данные для массива str в основной функцие main.
2.3.2 Алгоритмы и функции.
Программа состоит и нескольких функций, которые вызываются в главной функции main(). Далее представлены эти функции:
Алгоритм Шеннона-Фано, основан на теоретических знаниях. В функцию передается вся таблица, а также 2 важных параметра: размер блока и индекс начала этого блока. Принцип действия основан на рекурсии- то есть вызов функцией самой себя. В начале функции стоят проверки на размеры блоков:1,2,3-это особые случаи, в других случаях функция выполняет действия по разделу входного блока на 2 блока и присвоением первому блоку кода «0», а второму «1». На вход могут подаваться таблицы одно- двух- и трехбуквенных сочетаний символов, при этом нужно указывать размер первичного блока: 4, 16, 64 соответственно. При первом вызове рекурсивной функции начало блока ставится 0.
Построение кодов Шеннона-Фано: рекурсивная функция
Аргументы:указатель на сочетания,начало и конец кодируемого участка, сумма вер-тей, номер шага(глубина)
void fano_rec(soch *sochet[],int first,int last,double sump,int k){
Задаем сумму первой группы =0
разница между группами=2.0
номер рассматриваемой комбинации
количество комбинаций в первой группе=-1
//в первую группу заносим новые комбинации, пока разница сумм вероятностей у групп не будет минимальна
//Т.е. если при добавлении
новой комбинации разница
while (((razn > fabs(sump-2*(sum+sochet[i]->
увеличиваем суммму вер-стей первой группы
пишем ноль в код комбинации (она уже в первой группе)
увеличиваем количество комбинаций в первой группе на 1
вычисляем разницу между группами
i++;
}
while (i<=last) {sochet[i]->code[k]='1';i++;}/
//запускаем рекурсию в
каждой из групп или
if (ss>0) fano_rec(sochet,first,first+
else sochet[first]->code[k+1]='\0';
if (last-first-ss>1) fano_rec(sochet,first+ss+1,
else sochet[last]->code[k+1]='\0';
}
//Построение кодов Шеннона-Фано
void fano(soch *sochet[],int n){
//Сортируем вероятности
soch *t;
for(int i=0; i<n; i++)
for(int j=n-1; j>i; j--)
if ((sochet[j-1]->ver < sochet[j]->ver)){
t=sochet[j];sochet[j]=sochet[
}
//Запускаем рекурсивную функцию
fano_rec(sochet,0,n-1,1.0,0);
}
//Построение кодов хаффмана
void haffman(soch *sochet[],int n){
//Сортируем вероятности (методом пузырька)
soch *t;
for(int i=0; i<n; i++)
for(int j=n-1; j>i; j--)
if ((sochet[j-1]->ver < sochet[j]->ver)){
t=sochet[j];sochet[j]=sochet[
}
//создаем дерево (с помощью параллельных массивов)
Задаем родителя вершины
Задаем бит вершины (символ)
Задаем вероятность
int res_ver[2*MAXL]={0};
int res_i[2*MAXL]={0};
//задаем листья (все исходные комбинации)
for (int i=0; i<n; i++) {
бит вершиы=-1;
родитель вршины=-1;
вероятность=sochet[i]->ver;
}
//начинаем кодировку
Задаем колличество
while (1) {
задаем переменные minn1 и minn2
находим 2 минимальные вершины без кодов
//первая вершина
Задаем min=2.0
for (int i=0; i<count; i++) {
if (бит вершины==-1 && вероятность<=min) {min=вероятнсти;minn1=i;}
}
//вторая вершина
Задаем min=2.0;
for (int i=0; i<count; i++) {
if (бит вершины==-1 && вероятность<=min && minn1!=i) {min=вероятности;minn2=i;}
}
Присваеваем биту вершины[minn1]=1;
Присваеваем биту вершины[minn2]=0;
если постороенно полное дерево, то выходим
иначе добавляем родителя
бит родителя пока неизвестен
родителей пока нет
приписываем первому сыну номер родителя
приписываем второму сыну номер родителя
вероятность родителя = сумме вероятностей сыновей
count++;
}
//от каждого листа идём к корню дерева и запоминаем код
for (int i=0; i<n; i++) {
задаем переменные p=i,k=0;
while (p!=-1) {//пока не придём к корню
sochet[i]->code[k]='0'+der_
p=der_rod[p];
k++;
}
приписываем символ конца строки
"разворачиваем" код
for (int j=0;j<k/2;j++) {
char temp=sochet[i]->code[j];
sochet[i]->code[j]=sochet[i]->
sochet[i]->code[k-1-j]=temp;
}
}
}
//soch- сочетания, n- колво, in- входная строка, out- полученный код, k- количество символов в комбинации
//Примечание: Из строки берётся количество символов кратное k, остальные отбрасываются
void encode(soch *sochet[],int n,char in[MAXL],char out[MAXL*5],int k) {
задаем массив типа char
задаем переменные i=0 и j
out[0]='\0';
while (i<strlen(in)/k*k) {//отбрасываем неполные комбинации
берём нужную нам комбинацию из строки
for (j=0;(strcmp(tofind,sochet[j]-
strcpy(out+strlen(out),sochet[
i+=k;
}
}
void decode(soch *sochet[],int n,char in[MAXL*5],char out[MAXL]) {
char tofind[MAXL];
soch *sortsochet[MAXL]; //копия входных сочетаний, будет отсортирована
int i=0,j,ncode=0,scode=0;
char ch;
out[0]='\0';
//Sort
for(i=0; i<n; i++) sortsochet[i]=sochet[i];
soch *t;
for(i=0; i<n; i++) {
for(int j=n-1; j>i; j--)
if (strcmp(sortsochet[j-1]->code,
t=sortsochet[j];sortsochet[j]=
}
}
//
i=0;
while (i<strlen(in)) {//пока не прочитаем всё сообщение
ch=in[i];//берём символ
//находим подходящую
while (sortsochet[ncode]->code[
ncode++;
scode++;//сдвигаемся к
//Если код полный, значит мы нашли комбинацию символов
if (sortsochet[ncode]->code[
strcpy(out+strlen(out),
scode=0;
ncode=0;
}
i++;
}
}
void show(soch *sochet[],int n)
{
Задаем среднее=0
Задаем энтропию=0
for (int i=0; i<n; i++) {
копим среднюю длину
вычисляем энтропию
выводим на консоль символ, его вероятность и код
}
выводим энтропию
выводим среднюю длину
Выводим избыточность
}
int main(){
задае сообщение в массив в соответствии с вариантом
задаем переменные i,j,n1=0,n2=0,n3=0;
задаем переменные символьного типа ch,ch1,ch2,ch3;
задаем перееменную c;
задаем энтропию ent=0;
задаем массив вероятностей p[4];
soch *sochet3[64],*sochet2[16], *sochet1[4];
выводим на консоль Veroyatnosti и p
for (ch='a';ch<='d';ch++) {
выводим на консоль символ
c=0;
for (i=0;i<=strlen(str);i++)
if (str[i]==ch) c++;
считаем вероятность
выводим значение
считаем энтропию
}
Выводим значение энтропии на консоль
//формирование сочетаний
for (ch1='a';ch1<='d';ch1++) {
sochet1[n1]= new soch;
вероятность=p[ch1-'a'];
записываем символ
следующий столбец – конец строки
n1++;
for (ch2='a';ch2<='d';ch2++) {
sochet2[n2]= new soch;
вероятность=p[ch1-'a']*p[ch2-'
записываем первый символ в первый столбец
записываем второй символ во второй столбец
3й столбец – конец строки
n2++;
for (ch3='a';ch3<='d';ch3++) {
sochet3[n3]= new soch;
вероятность=p[ch1-'a']*p[ch2-'
записываем в первый столбец первый символ
записываем во второй столбец второй символ
записываем в третий столбец третий символ
записываем в последний столбец конец строки
n3++;
}
}
}
Задаем массив кода
Задаем массив докодированного сообщения
вызываем фунцию fano(sochet1,n1);
вызываем функцию fano(sochet2,
вызываем функцию fano(sochet3,
выводим на консоль Fano 1sim:
вызываем функцию show(sochet1,
вызываем функцию encode(
выводим на консоль kod:
вызываем функцию decode(
выводим на консоль str:
Выводим на консоль Fano 2sim
вызываем функцию show(sochet2,
вызываем функцию encode(
выводим на консоль kod:
вызываем функцию decode(
выводим на консоль str:
выводим на консоль Fano 3sim:
вызываем функцию show(sochet3,
вызываем функцию encode(
выводим на консоль kod:
вызываем функцию decode(
выводим на консоль str:
вызываем функцию haffman(
вызываем функцию haffman(
вызываем функцию haffman(
выводим на консоль Haffman 1sim:
вызываем функцию show(sochet1,
вызываем функцию encode(
выводим на консль kod:
вызываем функцию decode(
выводим на консоль str:
выводим на консоль Haffman 2sim:
вызываем функцию show(sochet2,
вызываем функцию encode(
выводим на консоль kod:
вызываем функцию decode(
выводим на консоль str:
выводим на консоль Haffman 3sim:
вызываем функцию show(sochet3,
вызываем функцию encode(
выводим на консоль kod:
вызываем функцию decode(
выводим на консоль str:
getch();
for (i=0;i<n1;i++) delete sochet1[i];
for (i=0;i<n2;i++) delete sochet2[i];
for (i=0;i<n3;i++) delete sochet3[i];
}
2.3.3 Тестирование.
Для проверки правильности работы программы использованы входные данные, которые были теоретически вычислены в ходе выполнения лабораторной работы №2.
Система Х: abcaaaaabbacbaacccabaccbbaccbb
Глава 3. Помехоустойчивое кодирование.
3.1 Задание.
1.Определить
исходные кодовые комбинации, соответствующие
заданному неприводимому
2. Построить циклические коды, соответствующие исходным кодовым комбинациям.
3. Выполнить
декодирование циклических
4. Внести ошибку в одну из кодовых комбинаций циклического кода.
5. Выполнить
декодирование циклического
6. Построить коды с проверкой на четность, с удвоением, с постоянным весом, инверсные, Грея для исходных кодовых комбинаций.
3.2 Теория.
Основные сведения о методах помехоустойчивого кодирования.
Помехоустойчивые коды применяют для уменьшения влияния помех на сообщения. Построение помехоустойчивых кодов основано на добавлении к исходной комбинации из k символов r контрольных символов. Закодированная комбинация будет составлять n символов. Поэтому помехоустойчивые коды часто называют (n, k)-коды.
Информация о работе Курсовая работа по «Теории информации и кодирования»