2010-04-01 4 views

Répondre

4

Traitez les 8 octets comme un entier non signé de 64 bits et convertissez-le en décimal et placez-le à gauche avec des zéros. Cela devrait faire pour la chaîne la plus courte possible, car elle utilise tous les chiffres disponibles dans toutes les positions sauf celle de départ.

Si vos données ne sont pas distribuées uniformément, il existe d'autres alternatives, en regardant dans Huffman-codage de sorte que le plus souvent les modèles de données peuvent être représentés par des chaînes plus courtes. Une façon consiste à utiliser le premier chiffre pour coder la longueur de la chaîne. Tous les nombres sauf 1 dans la première position peuvent être traités comme un spécificateur de longueur. De cette façon, la longueur maximale de 20 chiffres ne sera jamais dépassée. (Le 20ème chiffre ne peut être que 0 ou 1, le plus grand nombre de 64 bits est 18,446,744,073,709,551,615.) Le mappage d'interprétation exact des autres chiffres en longueurs doit être basé sur la distribution de vos motifs. Si vous avez 10 motifs qui se produisent très souvent, vous pourriez par exemple. réserver "0" pour signifier qu'un chiffre représente une séquence complète. Un tel codage plus complexe introduira cependant le besoin d'un code d'empaquetage/déballage plus complexe et peut-être même de tables de consultation, de sorte que cela n'en vaut pas la peine.

+1

... entier 64bit (unsigned) ... –

+1

Mais il sera aussi de longueur variable, ce qui nécessite un délimiteur entre les blocs dans le flux, ce qui serait ....? (Depuis que tous les dix chiffres ont été utilisés.) :-) –

+0

Merci pour les commentaires, j'ai corrigé et étendu ma réponse. –

1

Le résultat qui a la longueur la plus courte est de le convertir en décimal directement. Cela conduit à la valeur la plus élevée étant 18446744073709551615, mais la conversion peut être difficile sans capacité de longueur entière arbitraire.

Le plus long suivant est de le convertir en octal en un morceau. Cela se traduit par une longueur maximale de 22, avec une valeur de 1777777777777777777777. Cela nécessite seulement des changements de conversion, et peut être manipulé assez facilement.

Le plus long suivant est de le convertir en octal ou décimal bytewise. Cela se traduit par une longueur de 24, avec 8 répétitions de 377 ou 255 respectivement. Convertir en avant et en arrière est trivial, et est laissé comme un exercice pour le lecteur.

+0

Merci pour la réponse. Comme la première option est difficile sans capacité de longueur arbitraire, ce n'est pas vraiment un problème. Vous pouvez diviser le bloc en entiers de 4 octets, les convertir individuellement en décimal, puis les concaténer. Comme une valeur non signée de 4 octets prend au maximum 10 chiffres, nous avons toujours 20 chiffres pour un bloc de 8 octets. Qu'est-ce que tu penses? – Hemant

+0

C'est certainement une solution réalisable, tout comme il est divisé en 4 blocs de 2 octets de 5 chiffres chacun. –

+0

Avec la solution 2 fois 4 octets, vous devez surveiller les limites. Est-ce que 111 a 1 dans les octets supérieurs et 11 dans les octets inférieurs ou vice versa ou quoi? Vous devez donc toujours utiliser exactement 20 chiffres avec cette méthode. –

4

La réponse à la question d'efficacité dépendra d'un lot sur la plage de valeurs typique dans les blocs de 8 octets. Considérons UTF-8 et UTF-16 d'Unicode. UTF-8 est très efficace pour encoder des textes écrits principalement dans des scripts occidentaux, car la plupart des caractères dans ces scripts sont dans la plage 0x00 à 0x7F que UTF-8 peut stocker dans un seul octet. Mais ce n'est pas très efficace pour encoder des textes écrits principalement dans des scripts orientaux; UTF-16 ou UTF-32 est un meilleur choix là-bas.

Si vous avez une lecture sur the various UTFs, ils peuvent inspirer une solution. Fondamentalement, ils fonctionnent en faisant beaucoup de choses à encoder directement dans un octet, mais en ayant un drapeau (le bit de poids fort, je pense que c'est le cas, dans le cas du premier octet d'UTF-8) indiquant que octet ne dit pas toute l'histoire et le prochain octet (ou deux, ou trois, ou quatre) est/sont requis. Le point de départ est un octet pour UTF-8, un mot pour UTF-16, mais les concepts sont similaires.

Maintenant, vous travaillez avec un considérablement plus petite gamme de valeurs (0-9 plutôt que 0-255), et évidemment, je ne recommande pas d'essayer d'utiliser directement UTF, juste le concept. Par exemple, disons que la plupart de vos valeurs (directement ou avec un peu de massage) sont inférieures à 9000, certaines sont inférieures à 9000000, et seules des valeurs rares vous emmènent au-delà. Vous pouvez utiliser l'approche UTF et dire que les blocs (vos valeurs de 8 octets) sont divisés en segments à quatre chiffres, et vous aurez toujours au moins un segment (quatre chiffres) par bloc codé.Si la valeur du premier segment (aaaa) est comprise entre 0000 et 8999 (inclus), c'est un segment «terminal»   — qui est la valeur réelle. Mais si c'est 9aaa, cela signifie qu'il y a un deuxième segment et vous devriez regarder aaabbbb (bbbb étant la valeur du prochain segment). Si cette valeur est entre 0000000 et 8999999 (inclus), c'est un terminal; mais si c'est 9aabbbb, cela signifie regarder aabbbbcccc (cccc étant le segment suivant); etc. Je pense qui nous donnerait ceci:

00000000000000000000-00000000000000008999 -> 4 digits (xxxx) 
00000000000000009000-00000000000008999999 -> 8 digits (9xxxxxxx) 
00000000000009000000-00000000008999999999 -> 12 digits (99xxxxxxxxxx) 
00000000009000000000-00000008999999999999 -> 16 digits (999xxxxxxxxxxxxx) 
00000009000000000000-00008999999999999999 -> 20 digits (9999xxxxxxxxxxxxxxxx) 
00009000000000000000-08999999999999999999 -> 24 digits (99999xxxxxxxxxxxxxxxxxxx) 
09000000000000000000-18446744073709551615 -> 28 digits (999999xxxxxxxxxxxxxxxxxxxxxx) 
Or special case, just use 26 digits for the last one: (999999xxxxxxxxxxxxxxxxxxxx)

Il est votre meilleur cas quatre chiffres et le pire est 28 ou 26, selon que vous voulez cas spécial le dernier segement dans le bloc. Beaucoup mieux (probablement) que d'utiliser 20 chiffres pour chaque bloc. Maintenant, c'est complètement décalé et probablement pas aussi efficace qu'il pourrait l'être, mais vous avez l'idée. C'est très facile à désérialiser, et probablement pas si difficile à sérialiser.

Vous pouvez voir pourquoi j'ai commencé par le commentaire sur les valeurs typiques. S'ils sont généralement supérieurs à 10 000 000 000 000 000 000, ce qui précède n'est pas un moyen efficace de les encoder directement. Mais des techniques similaires peuvent être utilisées si vos valeurs typiques sont au niveau haut plutôt que bas, en massant la valeur un peu avant l'encodage.

Questions connexes