Me gustaría que un esquema represente números enteros que comiencen por 0, sin ningún límite (suponiendo el acceso al almacenamiento lineal infinito).
Aquí hay un esquema que puede representar números del 0 al 255:
Use el primer byte del almacenamiento (dirección 0) para almacenar el entero.
Ahora, supongamos que quiero representar números mayores que 255. Por supuesto, podría usar más de 1 byte para representar el número entero, pero mientras sea un número fijo, eventualmente habrá un número entero tan grande que no puede ser representado por El esquema original.
Aquí hay otro esquema que debería ser capaz de hacer la tarea, pero probablemente esté lejos de ser eficiente.
Simplemente use algún tipo de byte único de "fin de número" y use todos los bytes anteriores para representar el número. Obviamente, este byte "fin de número" no se puede usar en ninguna parte de la representación numérica, pero esto se puede lograr usando un sistema de numeración base-255 (en lugar de base-256).
Sin embargo, eso es lento y probablemente ineficiente. Quiero tener uno mejor que funcione mejor con valores bajos y escale bien.
Esencialmente, es un sistema UUID. Quiero ver si es posible crear un sistema UUID de rendimiento rápido que, en teoría, pueda escalar para usar durante años, miles de años, millones de años, sin tener que rediseñarlo.
Respuestas:
Un enfoque que he usado: contar el número de 1 bit inicial, por ejemplo
n
. El tamaño del número es entonces 2 ^ n bytes (incluidos los 1 bits iniciales). Tome los bits después del primer bit 0 como un entero y agregue el valor máximo (más uno) que puede ser representado por un número usando esta codificación en 2 ^ (n-1) bytes.Así,
Este esquema permite que cualquier valor no negativo se represente exactamente de una manera.
(De manera equivalente, usé el número de 0 bits iniciales).
fuente
Hay mucha teoría basada en lo que estás tratando de hacer. Eche un vistazo a la página wiki sobre códigos universales : hay una lista bastante exhaustiva de métodos de codificación de enteros (algunos de los cuales se están utilizando en la práctica).
O simplemente puede usar los primeros 8 bytes para almacenar la longitud del número en algunas unidades (bytes más probables) y luego colocar los bytes de datos. Sería muy fácil de implementar, pero bastante ineficiente para números pequeños. Y podría codificar un número entero el tiempo suficiente para llenar todas las unidades de datos disponibles para la humanidad :)
fuente
¿Qué tal si el número de los primeros 1 más el primer 0 sea el tamaño (sizeSize) del tamaño del número (numSize) en bits. NumSize es un número binario que proporciona el tamaño de la representación del número en bytes, incluidos los bits de tamaño. Los bits restantes son el número (num) en binario. Para un esquema entero positivo, aquí hay algunos ejemplos de números de ejemplo:
fuente
¿Qué tal eso? Un byte para la longitud, luego n bytes para el número (primero el byte menos significativo). Repita longitud + número siempre que la longitud anterior fuera 255.
Esto permite números arbitrariamente grandes, pero sigue siendo fácil de manejar y no desperdicia demasiada memoria.
fuente
¿Por qué no usar solo 7 bits de cada byte y usar el octavo bit para indicar si hay otro byte a seguir? Entonces 1-127 estaría en un byte, 128 estaría representado por 0x80 0x01, etc.
fuente
Los sistemas UUID se basan en una potencia informática limitada (pero grande) en un universo finito (pero grande). El número de UUID es grande incluso en comparación con cosas absurdamente grandes como el número de partículas en el universo. Sin embargo, el número de UUID, con cualquier número de bits fijos, es pequeño, en comparación con el infinito.
El problema con el uso de 0xFFFF para representar su indicador de fin de número es que hace que la codificación de su número sea menos eficiente cuando los números son grandes. Sin embargo, parece que su esquema UUID empeora este problema. En lugar de omitir uno de cada 256 bytes, ahora tiene todo el espacio UUID desperdiciado. La eficiencia de la computación / reconocimiento (en lugar del espacio) depende mucho de su computadora teórica (lo cual, supongo que tiene si está hablando de infinito). Para una TM con una cinta y un controlador de estado finito, cualquier esquema de UUID es imposible de escalar de manera eficiente (básicamente, el lema de bombeo evita que se mueva más allá de un marcador de extremo de longitud fija de manera eficiente). Si no asume un controlador de estado finito, esto podría no aplicarse, pero debe pensar dónde van los bits en el proceso de decodificación / reconocimiento.
Si solo desea una mejor eficiencia que 1 de 256 bytes, puede usar cualquier longitud de bit de 1s que iba a usar para su esquema UUID. Eso es 1 de 2 ^ longitud de bits en ineficiencia.
Sin embargo, tenga en cuenta que hay otros esquemas de codificación. La codificación de bytes con delimitadores resulta ser la más fácil de implementar.
fuente
Sugeriría tener una matriz de bytes (o ints o longs) y un campo de longitud que diga qué tan largo es el número.
Este es más o menos el enfoque utilizado por BigInteger de Java . El espacio de direcciones posible a partir de esto es masivo, lo suficientemente fácil como para dar un UUID diferente a cada átomo individual en el universo :-)
A menos que tenga una muy buena razón para hacerlo, sugeriría simplemente usar BigInteger directamente (o su equivalente en otros idiomas). No es necesario reinventar la rueda de números grandes ...
fuente
En primer lugar, gracias a todos los que contribuyeron con excelentes respuestas a mi pregunta relativamente vaga y abstracta.
Me gustaría aportar una respuesta potencial que he pensado después de pensar en otras respuestas. No es una respuesta directa a la pregunta formulada, pero es relevante.
Como algunas personas señalaron, el uso de un número entero de 64/128/256 bits ya le brinda un espacio muy grande para UUID. Obviamente no es infinito, pero ...
Tal vez sea una buena idea usar un tamaño fijo int (digamos, 64 bits para comenzar) hasta que 64 bits no sea suficiente (o esté cerca de él). Luego, suponiendo que tenga dicho acceso a todas las instancias anteriores de los UUID, simplemente actualícelos a todos a ints de 128 bits y considere que es su número entero de tamaño fijo.
Si el sistema permite tales pausas / interrupciones del servicio, y debido a que tales operaciones de "reconstrucción" deberían ocurrir con poca frecuencia, quizás los beneficios (un sistema muy simple, rápido y fácil de implementar) sobrepasarán las desventajas (tener que reconstruir todos los enteros previamente asignados) a un nuevo tamaño de bit entero).
fuente