Je voudrais qu'un schéma représente des nombres entiers commençant par 0, sans aucune limite (en supposant l'accès au stockage linéaire infini).
Voici un schéma qui peut représenter des nombres de 0 à 255:
Utilisez le premier octet de la mémoire (adresse 0) pour stocker l'entier.
Supposons maintenant que je veuille représenter des nombres supérieurs à 255. Bien sûr, je pourrais utiliser plus d'un octet pour représenter l'entier, mais tant qu'il s'agit d'un nombre fixe, il y aura finalement un entier si grand qu'il ne pourra pas être représenté par le schéma d'origine.
Voici un autre schéma qui devrait être en mesure de faire la tâche, mais il est probablement loin d'être efficace.
Utilisez simplement une sorte d'octet unique de "fin de numéro" et utilisez tous les octets précédents pour représenter le nombre. Évidemment, cet octet de "fin de nombre" ne peut être utilisé nulle part dans la représentation numérique, mais cela peut être réalisé en utilisant un système de numérotation base-255 (au lieu de base-256).
Cependant, c'est lent et probablement inefficace. Je veux en avoir un meilleur qui fonctionne mieux avec des valeurs faibles et qui évolue bien.
C'est essentiellement un système UUID. Je veux voir s'il est possible de créer un système UUID à performance rapide qui peut théoriquement évoluer pour être utilisé pendant des années, des milliers d'années, des millions d'années, sans avoir à être repensé.
Réponses:
Une approche que j'ai utilisée: compter le nombre de bits 1 en tête, par exemple
n
. La taille du nombre est alors de 2 ^ n octets (y compris les 1 premiers bits). Prenez les bits après le premier 0 bit comme un entier et ajoutez la valeur maximale (plus un) qui peut être représentée par un nombre en utilisant ce codage en 2 ^ (n-1) octets.Donc,
Ce schéma permet à toute valeur non négative d'être représentée d'une seule manière.
(De manière équivalente, utilisé le nombre de bits 0 de tête.)
la source
Il y a beaucoup de théorie basée sur ce que vous essayez de faire. Jetez un oeil à la page wiki sur les codes universels - il y a une liste assez exhaustive des méthodes de codage entier (dont certaines sont en fait utilisées dans la pratique).
Ou vous pouvez simplement utiliser les 8 premiers octets pour stocker la longueur du nombre dans certaines unités (les octets les plus probables), puis mettre les octets de données. Il serait très facile à mettre en œuvre, mais plutôt inefficace pour les petits nombres. Et vous seriez en mesure de coder un entier suffisamment longtemps pour remplir tous les lecteurs de données disponibles pour l'humanité :)
la source
Que diriez-vous de laisser le nombre de 1 en tête plus le premier 0 être la taille (sizeSize) de la taille du nombre (numSize) en bits. NumSize est un nombre binaire qui donne la taille de la représentation numérique en octets, y compris les bits de taille. Les bits restants sont le nombre (num) en binaire. Pour un schéma d'entier positif, voici quelques exemples de numéros d'exemple:
la source
Que diriez-vous de cela: un octet pour la longueur, puis n octets pour le nombre (octet le moins significatif en premier). Répétez longueur + nombre tant que la longueur précédente était de 255.
Cela permet des nombres arbitrairement grands, mais est toujours facile à gérer et ne gaspille pas trop de mémoire.
la source
Pourquoi ne pas simplement utiliser 7 bits sur chaque octet et utiliser le 8e bit pour indiquer s'il y a un autre octet à suivre? Ainsi, 1-127 serait dans un octet, 128 serait représenté par 0x80 0x01, etc.
la source
Les systèmes UUID sont basés sur une puissance de calcul finie (mais grande) dans un univers fini (mais grand). Le nombre d'UUID est important même par rapport à des choses absurdement grandes comme le nombre de particules dans l'univers. Le nombre d'UUID, avec un nombre quelconque de bits fixes, est cependant petit par rapport à l'infini.
Le problème avec l'utilisation de 0xFFFF pour représenter votre indicateur de fin de numéro est qu'il rend l'encodage de votre numéro moins efficace lorsque les nombres sont grands. Cependant, il semble que votre schéma UUID aggrave encore ce problème. Au lieu d'un octet sur 256 ignoré, vous avez maintenant tout l'espace UUID perdu. L'efficacité du calcul / reconnaissance (au lieu de l'espace) dépend beaucoup de votre ordinateur théorique (ce que je suppose que vous avez si vous parlez de l'infini). Pour une MT avec une bande et un contrôleur à états finis, tout schéma UUID est impossible à mettre à l'échelle efficacement (fondamentalement, le lemme de pompage vous empêche de dépasser efficacement un marqueur d'extrémité à longueur de bit fixe). Si vous ne supposez pas un contrôleur d'état fini, cela peut ne pas s'appliquer, mais vous devez penser à où vont les bits dans le processus de décodage / reconnaissance.
Si vous voulez simplement une meilleure efficacité que 1 octet sur 256, vous pouvez utiliser la longueur de bit de 1 que vous alliez utiliser pour votre schéma UUID. C'est 1 sur 2 ^ bits d'inefficacité.
Notez qu'il existe cependant d'autres schémas d'encodage. Le codage d'octets avec des délimiteurs se trouve être le plus facile à implémenter.
la source
Je suggère d'avoir un tableau d'octets (ou des entiers ou des longs) et un champ de longueur qui indique la longueur du nombre.
C'est à peu près l'approche utilisée par BigInteger de Java . L'espace d'adressage possible est énorme - assez facilement pour donner un UUID différent à chaque atome individuel dans l'univers :-)
Sauf si vous avez une très bonne raison de faire autrement, je vous suggère d'utiliser directement BigInteger (ou son équivalent dans d'autres langues). Plus besoin de réinventer la roue des grands nombres ...
la source
Tout d'abord, merci à tous ceux qui ont apporté d'excellentes réponses à ma question relativement vague et abstraite.
Je voudrais apporter une réponse potentielle à laquelle j'ai pensé après avoir pensé à d'autres réponses. Ce n'est pas une réponse directe à la question posée, mais elle est pertinente.
Comme certaines personnes l'ont souligné, l'utilisation d'un entier de taille 64/128/256 bits vous donne déjà un très grand espace pour les UUID. Ce n'est évidemment pas infini, mais ...
Peut-être que ce serait une bonne idée d'utiliser simplement une taille fixe int (disons, 64 bits pour commencer) jusqu'à ce que 64 bits ne soit pas suffisant (ou proche). Ensuite, en supposant que vous ayez un tel accès à toutes les instances précédentes des UUID, il vous suffit de les mettre à niveau en entiers 128 bits et de prendre cela comme votre taille fixe d'entier.
Si le système autorise de telles pauses / interruptions de service, et parce que de telles opérations de "reconstruction" doivent se produire assez rarement, les avantages (un système très simple, rapide et facile à mettre en œuvre) l'emporteront peut-être sur les inconvénients (devoir reconstruire tous les entiers précédemment alloués). à une nouvelle taille de bit entière).
la source