Есть массив из чисел в 10 бит (то есть максимум 1024 значения). Для его хранения нужно 2 байта * количество чисел. Можно поделить эти числа на 4 и получить возможность хранить числа в однобайтовом массиве. Но тогда потеряются нижние значения - младшие биты. Есть ли алгоритм, который позволяет сохранять "верхние" и "нижние" биты и сжимать "середину" ? Например, числа 1000 и 2 превращаются в 232 и 2 или что-то подобное. Я понимаю, что если есть сразу весь массив, то можно проанализировать "середину" и выкинуть ее, отняв от чисел больше какого-то значения незначимую часть. Но что если массив еще не получен и есть только отдельные числа и для них для всех придется использовать алгоритм без знаний о том, что за результаты будут в конце?
Да, такой вариант тоже рассматриваю. Пока не уверен. Можно найти кратное число элементов массива, чтобы совпадало. Но тут, как мне кажется, что сэкономить можно чуть больше "сжав" числа.
Ну сжатий есть 2 вида. С потерями и без потерь. С потерями это у вас же - отрезать 2 младших бита.
Без потерь вам уже советовали - коды хаффмана, RLE, или какой-нибудь стандартный обобщенный сжиматель, типа zlib.
Есть ли алгоритм, который позволяет сохранять "верхние" и "нижние" биты и сжимать "середину" ?
Довольно сумбурно выражена мысль, но дайте я догадаюсь:
Чтобы у маленьких чисел не терялись младшие биты, а у больших не терялись старшие?
Если я вас правильно понял, то поздравляю, вы изобрели числа с плавающей точкой.
А хватит ли одного байта, чтобы сохранить числа с плавающей точкой?
Получается, что, например, старший бит означает умножение на 8. Число 1023 будет записано как b11111111, то есть 1016, а все, что меньше 128 будет записываться без старшего бита. Тогда всё от 0 до 127 будет сохраняться правильно, только в верхних областях будет округление до 8. Это самое простое, что пришло в голову. Но хотелось бы, чтобы точность ближе к верхней и нижней части была максимальная, а середина пусть будет менее точной.
we1, стандартно - не хватит. Но вы же всё равно свой формат придумываете.
Простейший вариант:
старший бит - порядок: когда =0, то берём мантиссу без изменений, когда =1, то умножаем мантиссу на 8.
7 младших бит дают мантиссу от 0 до 127.
127*8=1016, но в этом формате уже будут не отличимы друг от друга 1016, 1017,.. 1023
Другой вариант:
два старших бита - порядок: когда =01, то умножаем мантиссу на 4, когда =10, то умножаем мантиссу на 16, когда =11, то умножаем мантиссу на 64
6 младших бит дают мантиссу от 0 до 63. Таким образом можно записать числа уже от 0 до 4095.
У меня не получается сначала сделать массив. Так было бы намного проще. Мне надо сразу класть в массив уменьшенные числа (это все из-за ограничения память в микрокотроллере). Конечно, я могу сохранять предыдущее значение и сохранять разницу, но разница может превышать 255 или +/-127
Antonio Solo, в основе многих архиваторов лежит принцип неизменности тех данных, которые нужно сжать. И если на заданных данных граничные условия не соблюдаются - соответствующее сжатие не применяется, так как оно только увеличивает объем результата. Делать то же самое для динамических данных - только создавать головную боль на ровном месте.
p.s. ежу понятно, что разрабатывая алгоритм сжатия, надо иметь представление (предположение) о характере того что ты сжимаешь. у ТС судя пор всему - результаты измерений. обычно они великолепно жмутся методом хранения разницы.
Antonio Solo, только для измерения явлений с малой волатильностью. Кардиограмму так не сожмешь, например.
Вообще, это гадание на кофейной гуще. Какие-то данные, какая-то экономия. Ткнуть пальцем и уверенно сказать, что здесь можно будет вот так сэкономить, а не потерять лишнюю память на сжатие и получить еще больший результат, все равно невозможно.
Ваша проблема сформулирована как задача о семиугольном треугольнике.
Лучше сформулировать более общую проблему - что за числа, как их нужно обрабатывать - и, возможно, вам подскажут более адекватное решение.
Сергей Соколов, так просто нельзя. Никто не знает, когда настоящая "середина" окажется в районе 4 и 5 битов. Может оказаться, что максимальные значения именно на эти биты приходятся.
we1, тогда делайте из 10-битного числа 6-битное, а в верхних двух битах обозначайте позицию, откуда выкинуты средние 4 бита. Но точность у вас пойдет по... не очень точно будет, скажем так.
we1, не зная заранее, где будет середина, невозможно именно эту середину выкинуть. Можно вот как, но это для фиксированного диапазона, вам не очень подойдёт: