Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.45 KB | None | 0 0
  1. #include <iostream>
  2. #include <map>
  3. #include <fstream>
  4. #include <cmath>
  5.  
  6. struct symbol {     // структура для символа
  7.     char c;         // символ
  8.     int n;          // количество в тексте
  9.     long double p;       // вероятность
  10.     long double a_beg;   // начало отрезка
  11.     long double a_end;   // конец отрезка
  12.  
  13.     symbol(char c) : c(c) {
  14.         n = 1;
  15.     }
  16. };
  17.  
  18. std::map<char, symbol> symbols;
  19. std::string str;
  20. int size = 0;
  21.  
  22. void read_from_file(std::string filename) {                                  // считывание с файла
  23.     std::ifstream in(filename);
  24.     int sum = 0;                                         // кол-во символов
  25.     if (in.is_open()) {                                  // чтение посимвольно с файла и сохранение количества каждого типа символов в map
  26.         while (!in.eof()) {
  27.             char c = in.get();
  28.             auto iter = symbols.find(c);
  29.             if (iter != symbols.end()) {                  // если символ уже встречался -- увеличим счетчик
  30.                 iter->second.n++;
  31.             } else {
  32.                 symbol s = symbol(c);                     // если символ еще не встречался, создадим элемент в мапе
  33.                 symbols.insert({c, s});
  34.             }
  35.             sum++;
  36.             size++;
  37.         }
  38.         for (auto &symbol : symbols) {                   // расчет вероятностей
  39.             symbol.second.p = (double) symbol.second.n / (double) sum;
  40.         }
  41.     } else {
  42.         std::cout << "Файл не найден";
  43.     }
  44.     size--;
  45.     in.close();
  46. }
  47.  
  48. void read_string(std::string filename) {
  49.     std::ifstream in(filename);
  50.     if (in.is_open()) {
  51.         getline(in, str);
  52.     }
  53.     in.close();
  54. }
  55.  
  56. void make_segments() {                                   // создание границ отрезков
  57.     double courser = 0;
  58.     for (auto &s : symbols) {
  59.         s.second.a_beg = courser;
  60.         courser += s.second.p;
  61.         s.second.a_end = courser;
  62.     }
  63. }
  64.  
  65. double code(long double a_beg, long double a_end, char *c) {      // кодирование информации
  66.     auto it = symbols.find(*c);
  67.     long double new_a_beg = a_beg + (a_end - a_beg) * it->second.a_beg;    // новые границы
  68.     long double new_a_end = a_beg + (a_end - a_beg) * it->second.a_end;
  69.     printf("%c [%.53Lf; %.53Lf) -> [%.53Lf; %.53Lf)\n", *c, a_beg, a_end, new_a_beg, new_a_end);
  70.     c++;
  71.     if (*c) {                                                               // продолжить рекурсивно, пока не найден конец файла
  72.         return code(new_a_beg, new_a_end, c);
  73.     } else {
  74.         return (new_a_beg + new_a_end) / 2;
  75.     }
  76. }
  77.  
  78. std::string decode(long double code, std::string res) {   //декодирование фразы
  79.     for (auto & character : symbols) {
  80.         if (code >= character.second.a_beg && code < character.second.a_end) {    // поиск символа
  81.             res += character.first;
  82.             code = (code - character.second.a_beg)/(character.second.a_end - character.second.a_beg);   //нормализация и новый код
  83.             size--;
  84.             if (!size) {
  85.                 return res;
  86.             }
  87.             return decode(code, res);       // рекурсивно, пока не найдем конец строки
  88.         }
  89.     }
  90. }
  91.  
  92. double H(){                                     // энтропия
  93.     double res = 0;
  94.     for (auto &item : symbols) {
  95.         res -= item.second.p * std::log2(item.second.p);
  96.     }
  97.     res *= str.size();
  98.     return res;
  99. }
  100.  
  101. int main() {
  102.     std::cout << "Введите имя файла\n";
  103.     std::string filename = "../input/test.txt";
  104.     std::cin >> filename;
  105.     read_from_file(filename);
  106.     read_string(filename);
  107.     make_segments();
  108.     long double res = code(0, 1, &str[0]);
  109.     std::cout << "Арифметическое кодирование фразы: \"" << str << "\"\n";
  110.     std::cout << "Результат: ";
  111.     printf("%.53Lf\n", res);
  112.     std::cout << "Декодированная строка: " << decode(res, "") << "\n";
  113.  
  114.     std::cout << "Коэффициент сжатия: " << H()/sizeof(res) << "\n";
  115.     return 0;
  116. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement