Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.54/26: Рейтинг темы: голосов - 26, средняя оценка - 4.54
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
1

Энтропия файла

18.11.2012, 13:16. Просмотров 4985. Ответов 40
Метки нет (Все метки)

Добрый день! Взгляните опытным взглядом на код. Может в самом коде ошибка не связанная с типом результата.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void entropy(void)
{
    FILE *pf = NULL;
    char file[SIZE];
    int     ch, i, total = 0;
    int     code[256] = {0};
    float   entr = 0;
 
    Messages(2);
    printf("\n\n");
    system("DIR /a:-d");
    
    
    printf("\n Введите имя файла: ");
    gets(file);
    pf = fopen(file, "rt"); // Открытие файла для чтения
    if(pf == NULL)
    {
        Messages(3);
        printf("\n Выбрать файл (ENTER) / Выход в меню (ESC)");
        if(getch() == 27)
            menu();
        else
            entropy();
    }
    while((ch = fgetc(pf)) != EOF)
    {
        code[ch]++;
        ch = fgetc(pf);
    }
 
    for(i = 0; i < 256; i++)
        total += code[i];
 
    for(i = 0; i < 256; i++)
        entr -= code[i]*log(((float)code[i])/total);
    entr /= log(2);
    printf("\n Энтрония: %6.3f ", entr);
    getch();
}
Результат работы программы, подскажите в чем может быть причина ошибки. Вероятно это связано с типом float и отображением результата.

Энтропия файла
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.11.2012, 13:16
Ответы с готовыми решениями:

Что такое энтропия файла
Часто встречается подобный термин, в некоторых программах бывает(PEiD например). А что она из себя...

Энтропия
Изменение энтропии при различных тепловых процессах. Правила форума, пункт 4.3. Создавайте темы с...

Энтропия
Мужики, где тут идет вычисление энтропии? uses crt; var source:text; pr:string; {...

Энтропия
энтропия 1г азота при 25 градусах и давлении 10^5 Па равна 6,84 Дж/г*К. Определить энтропию 2г...

Энтропия
Нагреватель, сохраняющий постоянную температуру 100оС(неограниченный тепловой резервуар) приводится...

40
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 15:10 2
Когда количество какого-то символа равно нулю, то логарифм нуля даёт бесконечность, хотя в формуле энтропии 0*log(0) определяется равным нулю. Надо пропускать нулевые элементы. Ну и ещё разделить результат на общее количество символов.
C
1
2
3
4
5
    for(i = 0; i < 256; i++)
        if (code[i])
            entr -= code[i]*log(((float)code[i])/total);
    entr /= log(2)*total;
    printf("\n Энтропия: %6.3f\n", entr);
1
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 15:40  [ТС] 3
Спасибо получилось.
Есть еще вопрос. Все знаки препинания считались за один символ, как это можно реализовать в этом же коде.
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 15:46 4
Там, где символы подсчитываются можно знаки препинания заменять каким-то одним, например точкой.
Скажем, так:
C
1
2
3
4
5
6
7
    while((ch = fgetc(pf)) != EOF)
    {
        if (strchr(".,:!?'\"", ch))
            ch = '.';
        code[ch]++;
        ch = fgetc(pf);
    }
1
18.11.2012, 15:46
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 15:57  [ТС] 5
А как рассчитать энтропию для частоты пар символов и избыточность текста. В приведенном коде рассчитывается энтропия для одиночного символа.

Добавлено через 6 минут
На сколько я понимаю пары символов группируются в один или нет....
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 16:02 6
Если по простому, то можно создать массив размером 256*256 и вычислять индекс для пары символов так:
prev*256 + ch
где prev — это предыдущий символ, а ch — текущий. В конце итерации делать prev = ch и считывать новый.
Энтропия считается так же, но по всем парам. Для получения удельной энтропии на символ надо будет разделить на 2.
Избыточность (точнее коэффициент избыточности) 1 - entropy/max_entropy.

Интересно, а пробел относится к "знакам препинания" по заданию. А другие символы, скажем +-*/\|{}[]() и т. д.?
1
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 16:13  [ТС] 7
Я так понимаю нужно использовать отдельные циклы для двумерного массива или ....... До конца не понимаю весь процесс реализации. Представляем таблицу (массив) 256 на 256 на пересечении символ, так или я не верно рассуждаю.
Пробел так же считается за знак препинания и другие символы {}[]()/|\*+-.
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 16:25 8
Цитата Сообщение от Bugrimov Посмотреть сообщение
Я так понимаю нужно использовать отдельные циклы для двумерного массива или ....... До конца не понимаю весь процесс реализации. Представляем таблицу (массив) 256 на 256 на пересечении символ, так или я не верно рассуждаю.
Ну, примерно так. Правда я предлагал двумерный массив реализовать с помощью одномерного. И анализировать файл в таком же цикле как раньше, запомная предыдущую букву.
В строке aababaaaabba получится такая последовательность пар:
aa ab ba ab ba aa aa aa ab bb ba

Цитата Сообщение от Bugrimov Посмотреть сообщение
Пробел так же считается за знак препинания и другие символы {}[]()/|\*+-.
Тогда, может быть, проще наоборот, проверять является ли символ буквой, и если нет, то заменять на пробел. Для латинских символов (точнее для символов с кодами до 127) можно использовать функцию isalpha. Для русских, к сожалению, всё сложнее, так как результат зависит от локали и кодировки символов.
1
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 16:35  [ТС] 9
Цитата Сообщение от grizlik78 Посмотреть сообщение
Тогда, может быть, проще наоборот, проверять является ли символ буквой, и если нет, то заменять на пробел. Для латинских символов (точнее для символов с кодами до 127) можно использовать функцию isalpha. Для русских, к сожалению, всё сложнее, так как результат зависит от локали и кодировки символов.
С символами я думаю можно решение найти.
А по поводу пар символов. Каждой паре присваивается определенный символ или нет. Как цикл будет выглядеть?

Добавлено через 1 минуту
Для записи предыдущего символа использовать цикл while в описанном коде.
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 16:44 10
C
1
2
3
4
5
6
7
8
    prev = fgetc(pf);
    while((ch = fgetc(pf)) != EOF)
    {
        if (strchr(".,:!?'\"", ch))
            ch = '.';
        code[prev*256 + ch]++;
        prev = ch;
    }
Кстати, в исходном варианте лишний fgetc в конце цикла заметил. И в мой кусок кода он тоже перекочевал.
code[prev*256 + ch] можно заменить двухмерным массивом с индексацией code[prev][ch]
При вычислении энтропии будет либо одинарный цикл до 256*256, либо двойной, по 256 каждый.
0
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 16:55  [ТС] 11
Это отдельный цикл для пар символов?
Следующим шагом нужно реализовать подсчет пар символов отдельной переменной
C
1
2
for(i = 0; i < 256; i++)
        total += code[i];
Так?
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 16:57 12
Так:
C
1
2
for(i = 0; i < 256*256; i++)
        total += code[i];
0
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 17:10  [ТС] 13
Дальше энтропия вычисляется по такой же схеме.......
C
1
2
3
4
5
 for(i = 0; i < 256; i++)
        entr -= code[i]*log(((float)code[i])/total);
    entr /= log(2);
    printf("\n Энтрония для пар символов: %6.3f ", entr);
    getch();
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 17:14 14
Тут тоже надо 256*256 и результат разделить на 2*total. И опечатку в слове Энтрония исправить
0
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 17:54  [ТС] 15
Цитата Сообщение от grizlik78 Посмотреть сообщение
Энтрония исправить
Думаю это не получится.

Добавлено через 33 минуты
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
rewind(pf);
    total = 0;
    prev = fgetc(pf);
    while((ch = fgetc(pf)) != EOF)
    {
        if (strchr(".,:!?'\"", ch))
            ch = '.';
        code[prev*256 + ch]++;
        prev = ch;
    }
 
    for(i = 0; i < 256*256; i++)
        total += code[i];
    
    for(i = 0; i < 256*256; i++)
        entr_p -= code[i]*log(((float)code[i])/(2*total));
    entr_p /= log(2)*total;;
    printf("\n Энтропия для пар символов: %6.3f ", entr_p);
Выдает ошибку, результат не выводится.

Добавлено через 1 минуту
Код идет сразу после вывода результата по энтропии.
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 19:02 16
Двойку не туда прилепил. А размер массива 256*256?
C
1
2
3
    for(i = 0; i < 256*256; i++)
        entr_p -= code[i]*log(((float)code[i])/(total));
    entr_p /= log(2)*total*2;
0
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 19:12  [ТС] 17
Все равно выдает ошибку!!!
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
void entropy(void)
{
    FILE    *pf = NULL;
    char    file[SIZE];
    long    ch, prev, i, total = 0;
    int     code[256] = {0};
    float   entr = 0, entr_p = 0;
 
    Messages(2);
    printf("\n\n");
    system("DIR /a:-d");
    
    
    printf("\n Введите имя файла: ");
    gets(file);
    pf = fopen(file, "rt"); // Открытие файла для чтения
    if(pf == NULL)
    {
        Messages(3);
        printf("\n Выбрать файл (ENTER) / Выход в меню (ESC)");
        if(getch() == 27)
            menu();
        else
            entropy();
    }
    while((ch = fgetc(pf)) != EOF)
    {
        if(strchr(".,:;?!-\'\"", ch))   // Если в тексте встречаются знаки препинания
            ch = '.';                   // объединить в один символ '.'
        code[ch]++;
        
    }
 
    for(i = 0; i < 256; i++)
        total += code[i];
 
    for(i = 0; i < 256; i++)
        if(code[i])
        entr -= code[i]*log(((float)code[i])/total);
    entr /= log(2)*total;
    printf("\n Энтропия: %6.3f ", entr);
    
    /* Энтропия для пар символов */
    rewind(pf);
    total = 0;
    prev = fgetc(pf);
    while((ch = fgetc(pf)) != EOF)
    {
        if (strchr(".,:!?'\"", ch))
            ch = '.';
        code[prev*256 + ch]++;
        prev = ch;
    }
 
    for(i = 0; i < 256*256; i++)
        total += code[i];
    
    for(i = 0; i < 256*256; i++)
        entr_p -= code[i]*log(((float)code[i])/total);
    entr_p /= log(2)*total*2;
    printf("\n Энтропия для пар символов: %6.3f ", entr_p);
    fclose(pf);
    getch();
}
0
grizlik78
Эксперт С++
2050 / 1524 / 213
Регистрация: 29.05.2011
Сообщений: 3,161
18.11.2012, 19:28 18
В строке 6:
C
1
int     code[256*256] = {0};
1
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 19:37  [ТС] 19
Результат работы программы....
Энтропия файла
0
Bugrimov
4 / 4 / 0
Регистрация: 18.11.2012
Сообщений: 118
18.11.2012, 19:38  [ТС] 20
Какой-то непонятный результат
0
18.11.2012, 19:38
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.11.2012, 19:38

энтропия
Доброго времени суток. Нужно создать форму на которой будут следующие элементы: textbox, combobox,...

энтропия
в баллоне с жесткими стенками вместимостью 3 л находится инертный газ при давлении 120 кпа.Баллон...

Энтропия
Определить энтропию системы, которая может находиться в одном из 5 состояний, 4 из которых...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru