Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Энтропия текста 
:(
    Опции темы
Bugrimov
Дата 30.11.2012, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Заказчик говорит: "составить программу, определяющую энтропию текстового файла. Энтропию необходимо вычислить 2-мя способами, т.е. используя число отдельных символов и используя частоты пар символов. Файл содержит текст на естественном языке (русском или английском, строчные и заглавные символы не отличаются, знаки препинания объединены в один символ). В программе должна быть предусмотрена возможность смены необходимого текстового файла". Нужно найти энтропию и избыточность текста для одиночного символа и частоты пар символов. Вот такая задачка. smile  
PM MAIL   Вверх
feodorv
Дата 30.11.2012, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Bugrimov @  30.11.2012,  22:19 Найти цитируемый пост)
Заказчик говорит

Ну, это так задача сформулирована. А уточнить условия у него можно? Особенно по этому вопросу:
Цитата(Bugrimov @  30.11.2012,  21:21 Найти цитируемый пост)
Или учитываются все буквы алфавита.



Цитата(Bugrimov @  30.11.2012,  22:19 Найти цитируемый пост)
на естественном языке (русском или английском

То есть, на каком-то одном? Тогда можно сделать 2а варианта программы - для английского языка и русского отдельно. Можно попробовать сделать гибрид - если встречаются русские буквы, тогда русский текст, если английские - тогда английский, если и те, и другие - тогда смешанный текст...  




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Bugrimov
Дата 1.12.2012, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Смешанный текст...... Т.е. возможны русские и английские буквы в тексте.
PM MAIL   Вверх
feodorv
Дата 2.12.2012, 06:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Bugrimov @  1.12.2012,  11:09 Найти цитируемый пост)
Смешанный текст......

Как-то в задании говорится о русском или английском, но не о и русском, и английском одновременно. Мне кажется, лучше всего, всё-таки, уточнить условие задачи.

И если речь идёт именно о естественном языке, то, думаю, нужно учитывать все буквы алфавита, даже которые в тексте не встретились (для больших текстов это маловероятно).

Но если хочется смешанный текст, то стОит сделать гибрид:
  • отдельно считаются английские буквы
  • отдельно считаются русские буквы
  • отдельно считаются знаки препинания (точно к ним относятся все остальные символы?)
Для виндовой кодировки:
Код

int ch;
int rusCode[32], engCode[26], punCode;
int rusTotal, engTotal;

if( ch >= 'A' && ch <= 'Z' )
{
  endCode[ch - 'A']++;
  engTotal++;
}
else if( ch >= 'a' && ch <= 'z' )
{
  engCode[ch - 'a']++;
  engTotal++;
}
else if( ch == 'Ё' || ch == 'ё' )
{
  rusCode['е'-'а']++;
  rusTotal++;
}
else if( ch >= 'А' && ch <= 'Я' )
{
  rusCode[ch-'А']++;
  rusTotal++;
}
else if( ch >= 'а' && ch <= 'я' )
{
  rusCode[ch-'а']++;
  rusTotal++;
}
else
  punCode++;

И в конце уже смотреть, русский, английский или смешанный тип:
Код

if( engTotal == 0 && rusTotal == 0 )
{
   // не текст
}
else if( engTotal == 0 )
{
  // чиста русский текст
}
else if( rusTotal == 0 )
{
  // чиста английский текст
}
else 
{
  // смешанный текст
}


Правда, в таком случае придётся немного по-разному считать частоту парных символов...


Более грамотно, конечно, воспользоваться функциями setlocale, isalpha, tolower. В этом случае энтропию для одиночных символов и для парных символов можно считать за один проход файла (за одно чтение):
Код

int code[256] = { 0 }, code_p[256*256] = { 0 };
int rusTotal, engTotal, punTotal;
int ch, lastch = 0;

setlocale( LC_ALL, "Russian");
...

  if( isalpha(ch) )
  {
    ch = tolower(ch);
    if( ch == 'ё' ) ch = 'е';
    code[ch]++;
    if( ch >= 0x80 ) rusTotal++; else engTotal++;
    if( lastch != 0 ) code_p[ 256*lastch + ch ]++;
  }
  else 
  {
    ch = ' '; // всё остальное
    punTotal++;
    if( lastch != 0 ) code_p[ 256*lastch + ch ]++;
  }
  lastch = ch;

...
if( engTotal == 0 && rusTotal == 0 )
  ...
  ...
  ...



Ну и количество букв в алфавите будет зависеть от того, английский, русский или смешанный этот текст...


Это сообщение отредактировал(а) feodorv - 2.12.2012, 07:00


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Bugrimov
Дата 2.12.2012, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  2.12.2012,  06:53 Найти цитируемый пост)
Ну и количество букв в алфавите будет зависеть от того, английский, русский или смешанный этот текст...

Как будет выглядеть подсчет количества букв в алфавите например если текст на русском, на английском и смешанный. Как это можно вставить в мой программный код. Еще вопрос, как все таки выглядит тогда подсчет максимальной энтропии.
Цитата(feodorv @  2.12.2012,  06:53 Найти цитируемый пост)
отдельно считаются знаки препинания (точно к ним относятся все остальные символы?)
 Да, именно. smile 

PM MAIL   Вверх
feodorv
Дата 2.12.2012, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Bugrimov @  2.12.2012,  21:27 Найти цитируемый пост)
Как будет выглядеть подсчет количества букв в алфавите например если текст на русском, на английском и смешанный.

 smile Ну так число букв для каждого языка ведь известно? Достаточно сложить:
Код

int m;

if( engTotal == 0 && rusTotal == 0 )
{
   m = 1;
}
else if( engTotal == 0 )
{
   m = 32+1;
}
else if( rusTotal == 0 )
{
   m = 26+1;
}
else 
{
  m = 26+32+1;
}


Цитата(Bugrimov @  2.12.2012,  21:27 Найти цитируемый пост)
как все таки выглядит тогда подсчет максимальной энтропии.

Тупо по определению:
Цитата(feodorv @  28.11.2012,  08:42 Найти цитируемый пост)
max_entr = log(m)/log(2);




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Bugrimov
Дата 2.12.2012, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Я имел в виду в моем коде, он получается кардинально не верен smile Последний пример понятен. Это проверка на присутствие в тексте русских или латинских символов (так же их отсутствие или "гибрид"). Просто на вашем примере 
Код

int code[256] = { 0 }, code_p[256*256] = { 0 };
int rusTotal, engTotal, punTotal;
int ch, lastch = 0;
setlocale( LC_ALL, "Russian");
...
  if( isalpha(ch) )
  {
    ch = tolower(ch);
    if( ch == 'ё' ) ch = 'е';
    code[ch]++;
    if( ch >= 0x80 ) rusTotal++; else engTotal++;
    if( lastch != 0 ) code_p[ 256*lastch + ch ]++;
  }
  else 
  {
    ch = ' '; // всё остальное
    punTotal++;
    if( lastch != 0 ) code_p[ 256*lastch + ch ]++;
  }
  lastch = ch;
...
if( engTotal == 0 && rusTotal == 0 )
  ...
  ...
  ...


не совсем понятно - расчеты для символа и для пары символов (поясните пожалуйста некоторые строки). И как это будет вписываться в мой код? Это на сколько я понял идет проверка и подсчет символов перед расчетами энтропии.
PM MAIL   Вверх
feodorv
Дата 3.12.2012, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Bugrimov @  2.12.2012,  22:33 Найти цитируемый пост)
поясните пожалуйста некоторые строки

Какие именно? Просто вместо 
Цитата(Bugrimov @  26.11.2012,  19:08 Найти цитируемый пост)
    while((ch = fgetc(pf)) != EOF)
    {
        if(strchr(".,:;?!-\'\"", ch))    // Если в тексте встречаются знаки препинания
            ch = '.';                    // объединить в один символ '.'
        code[ch]++;    // Считает число символов каждого типа
        
    }

пишется, например, такое:
Код

int lastch = EOF; // EOF - лучше чем 0

...

while((ch = fgetc(pf)) != EOF)
{
  if( isalpha(ch) )
  {
    ch = tolower(ch);
    if( ch == 'ё' ) ch = 'е';
    code[ch]++;
    if( ch >= 0x80 ) rusTotal++; else engTotal++;
    if( lastch != EOF ) code_p[ 256*lastch + ch ]++;
  }
  else 
  {
    ch = '.'; // всё остальное
    code[ch]++;
    punTotal++;
    if( lastch != EOF ) code_p[ 256*lastch + ch ]++;
  }
  lastch = ch;
}
fclose(pf);

if( engTotal == 0 && rusTotal == 0 )
   m = 26 + 1; // будем считать, что это был английский текст...
else if( engTotal == 0 )
   m = 32+1;
else if( rusTotal == 0 )
   m = 26+1;
else 
   m = 26+32+1;

total = rusTotal + engTotal + punTotal;

for( i = 0; i < 256; i++)
   if( code[i] )
     entr -= (float) code[i] * log( (float) code[i] / (float) total);
entr /= log(2)*total;
max_entr = log(m)/log(2);

....

При этом одновременно считается и code и code_p (за один проход файла). Чтобы isalpha и tolower отрабатывали на русских буквах, нужно установить нужную локаль.

Ну а затем считается энтропия как у Вас в первоначальном коде.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Bugrimov
Дата 3.12.2012, 05:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Еще вопрос! А для пары символов энтропия и максимальная энтропия у меня верно определяются? Мне сказали, что я ошибаюсь. Или все верно достаточно подставить подсчитанные значения. И еще верно, что для пары символов нужно использовать log(2.7) вместо log(2)
PM MAIL   Вверх
feodorv
Дата 3.12.2012, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Bugrimov @  3.12.2012,  06:14 Найти цитируемый пост)
А для пары символов энтропия и максимальная энтропия у меня верно определяются? Мне сказали, что я ошибаюсь.

Правильно сказали)))

Должна быть двойная сумма 
Код

ent2 = - sum(i:total) sum(j:total) p(ij) * log( p(ij) )

где p(ij) - вероятность появления j-го символа после i-го (то есть пары символов ij).
Условная энтропия

Соответственно, максимальная условная энтропия достигается при равенстве всех вероятностей (то есть при условии независимости следования символов друг за другом и одинаковой частоты появления символов алфавита). Высчитывается аналогично первому случаю, надеюсь, Вы легко её определите smile

Добавлено @ 10:28
Цитата(Bugrimov @  3.12.2012,  06:14 Найти цитируемый пост)
И еще верно, что для пары символов нужно использовать log(2.7) вместо log(2) 

Если в первом случае используется логарифм по основанию 2, то и во втором тоже должно использоваться это же основание. Не вижу оснований для смены основания)))

В формуле Шенона используется некая константа, которая является, на самом деле, калибровочной константой. Например, можно так откалибровать понятие энтропии, что максимальная энтропия примет значение 1. Смена основания логарифма ведёт просто-напросто к изменению этой константы, поэтому 
Цитата
выбор основания системы логарифмов несуществен


Интересно, что при выборе единичного значения для калибровочной константы 
Цитата
в случае основания 2 единицу измерения энтропии называют «бит», в случае основания 10 — «дит», в случае основания e=2.718281828459045... — «нат». 


Откуда взялась в Ваших записях константа 2.7, мне сказать трудно, тем более она очень близка к значению числа e. Но единицы измерения энтропии должны быть одинаковы, что в первом случае, что во втором. В битах - значит, в битах)))

Это сообщение отредактировал(а) feodorv - 3.12.2012, 10:30


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
baldina
Дата 3.12.2012, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(volatile @  27.11.2012,  23:37 Найти цитируемый пост)
Приблизительно её можно оценить с помощью архиватора.
Архиваторы, асимтотично стремятся к некому пределу сжатия.

архиваторы используют адаптивное сжатие. если частоты известны заранее, можно получить код с минимальной избыточностью.

Добавлено через 5 минут и 51 секунду
Цитата

Степень энтропии источника данных означает среднее число битов на элемент данных, требуемых для её зашифровки без потери информации, при оптимальном кодировании.

так что после сжатия оптимальным образом (в два прохода, с построением таблицы частот), энтропия вычисляется просто.
PM MAIL   Вверх
Bugrimov
Дата 3.12.2012, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  3.12.2012,  10:16 Найти цитируемый пост)
ent2 = - sum(i:total) sum(j:total) p(ij) * log( p(ij) )

Не совсем понятно как происходит вычисление sum(i:total), sum(j:total) и p(ij). Можете продемонстрировать в коде. 

PM MAIL   Вверх
baldina
Дата 3.12.2012, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(Bugrimov @  3.12.2012,  17:40 Найти цитируемый пост)
sum(i:total), sum(j:total)

это не вычисляется, это символизирует двойную сумму. два вложенных цикла.  smile 
PM MAIL   Вверх
Bugrimov
Дата 3.12.2012, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 8.11.2012

Репутация: нет
Всего: нет



Значит я не верно понял, можете показать как эти суммы будут выглядеть в коде.
PM MAIL   Вверх
feodorv
Дата 3.12.2012, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Bugrimov @  3.12.2012,  20:56 Найти цитируемый пост)
можете показать как эти суммы будут выглядеть в коде. 

user posted image


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1535 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.