Я хотел бы, чтобы схема представляла целые числа, начиная с 0, без каких-либо ограничений (предполагая доступ к бесконечному линейному хранилищу).
Вот схема, которая может представлять числа от 0 до 255:
Используйте первый байт памяти (адрес 0) для хранения целого числа.
Теперь предположим, что я хочу представить числа, превышающие 255. Конечно, я мог бы использовать более 1 байта для представления целого числа, но, пока это фиксированное число, в конечном итоге будет целое число, настолько большое, что оно не может быть представлено оригинальная схема.
Вот еще одна схема, которая должна быть в состоянии выполнить задачу, но, вероятно, она далеко не эффективна.
Просто используйте какой-то уникальный байт «конца числа» и используйте все предыдущие байты для представления числа. Очевидно, что этот байт «конца числа» не может использоваться нигде в числовом представлении, но этого можно достичь, используя систему нумерации base-255 (вместо base-256).
Однако это медленно и, вероятно, неэффективно. Я хочу иметь лучший, который работает лучше с низкими значениями и хорошо масштабируется.
По сути, это система UUID. Я хочу посмотреть, возможно ли создать быстродействующую систему UUID, которая теоретически может масштабироваться для использования в течение многих лет, тысяч лет, миллионов лет без необходимости ее перепроектирования.
Ответы:
Подход, который я использовал: подсчитать количество старших 1 бит, скажем
n
. Размер числа составляет 2 ^ n байтов (включая первые 1 бит). Возьмите биты после первого 0-битного числа как целое число и добавьте максимальное значение (плюс один), которое может быть представлено числом с использованием этой кодировки в 2 ^ (n-1) байтах.Таким образом,
Эта схема позволяет любому неотрицательному значению быть представленным точно одним способом.
(Эквивалентно, используется количество ведущих 0 битов.)
источник
Существует целая теория, основанная на том, что вы пытаетесь сделать. Взгляните на вики-страницу о универсальных кодах - здесь приведен довольно исчерпывающий список методов целочисленного кодирования (некоторые из которых фактически используются на практике).
Или вы можете просто использовать первые 8 байтов для хранения длины числа в некоторых единицах (наиболее вероятных байтах), а затем поместить байты данных. Это было бы очень легко реализовать, но довольно неэффективно для небольших номеров. И вы сможете закодировать целое число достаточно долго, чтобы заполнить все диски данных, доступные человечеству :)
источник
Как насчет того, чтобы число первых 1 плюс первые 0 было размером (sizeSize) размера числа (numSize) в битах. NumSize - это двоичное число, которое дает размер представления числа в байтах, включая биты размера. Остальные биты - это число (num) в двоичном виде. Для положительной целочисленной схемы вот несколько примеров чисел:
источник
Как насчет этого: один байт для длины, затем n байтов для числа (сначала младший байт). Повторите длину + число, если предыдущая длина была 255.
Это допускает произвольно большие числа, но все же легко обрабатывается и не тратит слишком много памяти.
источник
Почему бы просто не использовать 7 бит из каждого байта и использовать 8-й бит, чтобы указать, есть ли еще один байт? Таким образом, 1-127 будет в одном байте, 128 будет представлен 0x80 0x01 и т. Д.
источник
Системы UUID основаны на конечной (но большой) вычислительной мощности в конечной (но большой) вселенной. Количество UUID велико даже по сравнению с абсурдно большими вещами, такими как количество частиц во вселенной. Однако число UUID с любым количеством фиксированных битов мало по сравнению с бесконечностью.
Проблема с использованием 0xFFFF для представления вашего флага конца номера состоит в том, что он делает вашу кодировку чисел менее эффективной при больших числах. Однако кажется, что ваша UUID-схема делает эту проблему еще хуже. Вместо пропущенного одного из 256 байтов теперь все пространство UUID потрачено впустую. Эффективность вычислений / распознавания (а не пространства) во многом зависит от вашего теоретического компьютера (который, я полагаю, у вас есть, если вы говорите о бесконечности). Для ТМ с магнитной лентой и контроллером конечного состояния любую схему UUID невозможно эффективно масштабировать (в принципе, лемма прокачки мешает вам эффективно выйти за конечный маркер фиксированной длины). Если вы не предполагаете наличие контроллера конечного состояния, это может не применяться, но вам нужно подумать о том, куда идут биты в процессе декодирования / распознавания.
Если вы просто хотите повысить эффективность, чем 1 из 256 байтов, вы можете использовать любую битовую длину 1 с, которую вы собирались использовать для своей схемы UUID. Это 1 из 2-х бит длины в неэффективности.
Обратите внимание, что существуют и другие схемы кодирования. Байтовое кодирование с разделителями оказывается наиболее простым в реализации.
источник
Я бы предложил иметь массив байтов (или целых или длинных) и поле длины, которое говорит о том, как долго это число.
Это примерно тот подход, который используется в Java BigInteger . Возможное из этого адресное пространство огромно - достаточно легко, чтобы дать разные UUID каждому отдельному атому во вселенной :-)
Если у вас нет веской причины поступить иначе, я бы предложил просто использовать BigInteger напрямую (или его эквивалент на других языках). Нет особой необходимости изобретать колесо большого числа ....
источник
Прежде всего, спасибо всем, кто дал отличные ответы на мой относительно неопределенный и абстрактный вопрос.
Я хотел бы внести потенциальный ответ, о котором я подумал, подумав о других ответах. Это не прямой ответ на заданный вопрос, но он актуален.
Как отмечали некоторые люди, использование целого числа размером 64/128/256 бит уже дает вам очень большое пространство для UUID. Очевидно, это не бесконечно, но ...
Возможно, будет хорошей идеей просто использовать фиксированный размер int (скажем, 64-битный для начала), пока 64-битный не будет достаточно (или близко к нему). Затем, предполагая, что у вас есть такой доступ ко всем предыдущим экземплярам UUID, просто обновите их до 128-битных целочисленных значений и примите это как целое число фиксированного размера.
Если система допускает такие паузы / прерывания обслуживания и поскольку такие операции «перестроения» должны выполняться довольно редко, возможно, преимущества (очень простая, быстрая и простая в реализации система) перевесят недостатки (необходимость перестраивать все ранее выделенные целые числа). к новому целочисленному размеру бита).
источник