|
Арифметическое кодирование. | ☑ | ||
---|---|---|---|---|
0
megabax
27.10.16
✎
10:04
|
Подскажите пожалуйста идею, как решить проблему потери точности при арифметическом кодировании. Допустим есть у меня вот такой код на C#
low = 0; high = 1; int i = next_simbol(); while (i != -1) { double range = high - low; double dhigh = range * dictionary.items[i].p; if (i > 0) { low = low + range * dictionary.items[i - 1].p; } high=low+dhigh; i = next_simbol(); } где low и high переменные типа double. Но уже при кодировании 21 буквы high и low отличаются только одной значащей цифрой, а дальше они вообще сливаются. Как можно решить эту проблему? Написать свои классы супервысокой точности? Или каким-то волшебным образом интервал сразу кодировать в бинарном коде? |
|||
1
megabax
27.10.16
✎
10:35
|
up
|
|||
2
Волшебник
модератор
27.10.16
✎
10:38
|
перестать заниматься хернёй
|
|||
3
Кирпич
27.10.16
✎
10:38
|
нифига не понял где тут дебет и где кредит
|
|||
4
megabax
27.10.16
✎
10:41
|
(2) Это не херня, это лабораторная работа в институте.
|
|||
5
Волшебник
модератор
27.10.16
✎
10:42
|
(4) все лабораторные работы в институтах - херня
|
|||
6
ovrfox
31.10.16
✎
20:02
|
Алгоритм, который здесь указан ничего не кодирует. (В смысле не уменьшает размер). Соответственно данное суммирование быстро приводит к переполнению переменных.
Советую проверить алгоритм. |
|||
7
megabax
31.10.16
✎
20:29
|
(6)Да, вы правы. Переделал вот так:
low = 0; high = 1; StringBuilder sb = new StringBuilder(); int i = next_simbol(); while (i != -1) { double range = high - low; RangeDictionaryItem item = dictionary.items[i] as RangeDictionaryItem; high = low + range * item.end; low = low + range * item.beg; sb.AppendFormat("{0};[{1};{2});{3};{4};{5}\n", i, low, high, range, item.beg, item.end); i = next_simbol(); } И обратный алгоритм: high = 1; low = 0; for (int i = 1; i <= count; i++) { DictionaryItem item=dictionary.items.Find( delegate(DictionaryItem litem) { return (litem as RangeDictionaryItem).beg <= (value - low) / (high - low) && (value - low) / (high - low) < (litem as RangeDictionaryItem).end; } ); output_text += item.simbol; double range = high - low; high = low+range * (item as RangeDictionaryItem).end; low = low + range * (item as RangeDictionaryItem).beg; } но проблема осталось. Успешно кодирует и декодирует только примерно 10 символов, а дальше уже не может отработать обратное декодирование. Возникла идея double заменить на decimal, но он тоже не безграничный. Вот непонятно, как тут быть? Кодировать блоками? Или вводить какие-то коэффициенты и когда разница становиться маленькой, умножать на них? Или может разработать свои суперточные числа? |
|||
8
NorthWind
31.10.16
✎
21:19
|
(7) >> Или может разработать свои суперточные числа?
Зачем? Если вам не хватает того, что после запятой, вы можете использовать то, что до. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |