Перейти к содержимому
  • 0
Oleshe

Как кодировать числа символами Юникода?

Вопрос

Предположим у нас есть цифра 128. Мы попускаем её через unicode.char и получаем символ. Этот символ мы пропускаем через string.byte и вот не задача, начиная с 127 уникодовского символа оно выдаёт 194. Если мы попустим 130 а не 128, мы получим 194.
Как сделать так что-бы цифры сохранялись без огромных циклов в символ и обратно?

Изменено пользователем Oleshe
Дописал

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Рекомендуемые сообщения

Из символа в байты:

local char = unicode.char(128)
local bytes = {char:byte(1, #char)}

print(table.unpack(bytes))
> 194 128

Из байтов в символ:

local bytes = {194, 128}
local char = string.char(table.unpack(bytes))

print(char)
> ┬А -- unicode.char(128)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

7 часов назад, ECS сказал:

Из символа в байты:


local char = unicode.char(128)
local bytes = {char:byte(1, #char)}

print(table.unpack(bytes))
> 194 128

 

 

Мы получаем 2 числа, а нужно одно. Возьмём число побольше, на пример 1007, получиться {207,175},. Как из них получить 1 цифру, ту-же 1007 которую мы и вкладывали?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, Oleshe сказал:

Мы получаем 2 числа, а нужно одно

Ну дык склей эти 2 байта через

byte1 << 8 | byte2

 

1 час назад, Oleshe сказал:

Как из них получить 1 цифру, ту-же 1007 которую мы и вкладывали?

Ту же самую - никак, библиотека unicode не имеет функции codepoint. Поэтому приходится довольствоваться string.char/string.byte и комбинировать их с unicode.char

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@Oleshe Какую задачу ты пытаешься решить? Для кодирования произвольных двоичных данных при помощи символов существует, например, стандарт Base64.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
7 часов назад, eu_tomat сказал:

Какую задачу ты пытаешься решить?

У меня есть циферки, их нужно записать в файл максимально сжато, желательно. В уникоде куча символов, то-есть мы можем записать целое число в 1 символ (Числа будут в диапазоне от 0 до 40000). Я тестил это и оно работало, но когда мы выходили за пределы string.byte оно ломалось и читало не правильно, за 2 :read оно читало 1 символ. Если совместить их нельзя то сделаем так,  что-бы оно записывало максимальные значение так, что-бы в итоге получилось нормальное. Что-бы не попутать в конце поставим ноль ( если на пример число 128, то мы записываем 127 и 1. Если число 129, то запишем 127 и 2. Если число 1007 то записываем 127 7 раз, а в конце 118. Еще не делал, так-что это пока теория. Пойду сделаю.:smile44:

Изменено пользователем Oleshe

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 часа назад, Oleshe сказал:

У меня есть циферки, их нужно записать в файл максимально сжато, желательно. В уникоде куча символов, то-есть мы можем записать целое число в 1 символ

Ты хочешь кодировать одним символом именно для визуальной компактности? Или требуется сократить объём в байтах?

 

Символов-то в юникоде много, но на компактность хранения это не особо влияет. Например, кодировка UTF-16 использует 2 байта для хранения одного символа. А кодировка UTF-8 использует переменное количество байт: от 1 до 4, что получается более компактно при преимущественном использовании ASCII-символов (чисел от 0 до 127), но не очень компактно при кодировании чисел в диапазоне 128-65535.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Нужно записать цифры и я думаю что писать их в 1 строку по символам будет лучше чем пихать таблицу через сериализацию.

Требуется сократить объем в байтах, размер итогового файла.

Придумал дополнение к ранее описанной схеме, мы не записываем 127 столько раз сколько надо для цифры, вместо него мы используем множитель для 127 (Сколько их будет) и цифру которая меньше 127, остаток. (Если надо 1000, то делим 1000 на 127, отделяем то, что после запятой и это будет 1 символом. Тот множитель который мы получили только что умножаем на 127 и отнимаем от 1000, это остаток, второй символ. 7(множитель, символ)111(остаток, символ))

Изменено пользователем Oleshe

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
5 часов назад, Oleshe сказал:

Требуется сократить объем в байтах, размер итогового файла.

Хорошо, с этим разобрались. А каков диапазон чисел? И каковы шансы встретить маленькие числа в сравнении с большими?

 

Если появление чисел в некотором диапазоне равновероятно, и для их кодирования достаточно, например, 16 бит, то не морочим себе голову и кодируем число двумя байтами. Или тремя, четырьмя и т.д.

 

А если короткие числа встречаются заметно чаще длинных, то можно адаптировать трюк, использованный в кодировке UTF-8. Он позволит хранить числа переменной длины. Но, к слову, в UTF-8 он реализован не самым эффективным образом с точки зрения компактности, т.к. при его создании преследовалась ещё и цель быстрого определения первого байта, кодирующего символ. Выбросив это требование, мы получим ещё по два дополнительных бита с каждого последующего байта.

 

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

 

Проиллюстрирую сказанное:

UTF-8 кодирует значащие биты таким образом:
1 байт  кодирует  7 бит: 0xxxxxxx
2 байта кодируют 11 бит: 110xxxxx 10xxxxxx
3 байта кодируют 16 бит: 1110xxxx 10xxxxxx 10xxxxxx
4 байта кодируют 21 бит: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Выбрасываем из UTF-8 быстрый поиск начала цепочки:
1 байт  кодирует  7 бит: 0xxxxxxx
2 байта кодируют 14 бит: 10xxxxxx xxxxxxxx
3 байта кодируют 21 бит: 110xxxxx xxxxxxxx xxxxxxxx
4 байта кодируют 28 бит: 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx

Продолжение цепочки для удобства можно кодировать старшим битом в каждом байте:
1 байт  кодирует  7 бит: 0xxxxxxx
2 байта кодируют 14 бит: 1xxxxxxx 0xxxxxxx
3 байта кодируют 21 бит: 1xxxxxxx 1xxxxxxx 0xxxxxxx
4 байта кодируют 28 бит: 1xxxxxxx 1xxxxxxx 1xxxxxxx 0xxxxxxx

При кодировании длины цепочки фиксированным количеством бит
  немного снижается эффективность кодирования коротких чисел,
  но заметно увеличивается для длинных:
1 байт  кодирует  6 бит: 00xxxxxx
2 байта кодируют 14 бит: 01xxxxxx xxxxxxxx
3 байта кодируют 22 бит: 10xxxxxx xxxxxxxx xxxxxxxx
4 байта кодируют 30 бит: 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

К этому добавлю, что хотя стандарт UTF-8 и не предусматривает использования более 4 байт для кодирования символа, в наших применениях мы не обязаны следовать этому правилу и можем компактно кодировать сколь угодно длинные числа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
10 часов назад, eu_tomat сказал:

А каков диапазон чисел? И каковы шансы встретить маленькие числа в сравнении с большими?

Не знаю. Большие цифры: звуковые частоты, задержка (Длинна звука) и adsr. Из маленьких цифр: наличие adsr, инструмент (Ну там-ж пилавые, квадратные, треугольникавые, круглые звуковые волны), канал, и предохранитель на то, есть ли следующая "часть".


Вот сделал +- норм сжатие. Оно превращает:

2,1,2000,4000,2,1000,10,1,1000 -- с ADSR

2,2,2000,4000,2 -- Без ADSR

2,3,2000,4000,2,0,2000,0,1 -- c ADSR

В 38 байт:

�����o -- (В майне оно занимает больше символов. В AkelPad-е 3 сноса cтрок и пустые символы. Интересно.)

Возможно вы найдёте путь сжать еще сильнее.

Изменено пользователем Oleshe

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, Oleshe сказал:

Большие цифры: звуковые частоты, задержка (Длинна звука) и adsr. Из маленьких цифр: наличие adsr, инструмент (Ну там-ж пилавые, квадратные, треугольникавые, круглые звуковые волны), канал, и предохранитель на то, есть ли следующая "часть".

Я плохо разбираюсь в теме кодирования звука, но предполагаю, что все перечисленные значения должны регулярно следовать друг за другом. В этом случае определяем, сколько требуется бит для хранения каждого из значений, и все их кодируем единой пачкой байт постоянного размера. Если же некоторые из значений присутствуют в пачке не регулярно, то действуем по обстоятельствам. Возможно, в пачке из целого числа байт ещё имеются незадействованные биты. Тогда просто резервируем их под это значение. В противном случае резервируем один бит, сообщающий о присутствии или отсутствии этого опционального значения. Эти варианты напрашиваются первыми.

 

4 часа назад, Oleshe сказал:

от сделал +- норм сжатие. Оно превращает: ...

В 38 байт: ...

(В майне оно занимает больше символов. В AkelPad-е 3 сноса cтрок и пустые символы. Интересно.)

Эти закорючки не несут никакой полезной информации. Во-первых, есть непечатаемые символы, имеющие служебное назначение. Какой-то редактор может их отобразить, какой-то пропустит, какой-то интерпретирует особым образом. Например, обязательным образом интерпретируются символы переноса строк и табуляции, хотя даже в интерпретации переносов строк нет единого стандарта.

 

5 часов назад, Oleshe сказал:

Возможно вы найдёте путь сжать еще сильнее.

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...