Peu d'emballage de tableau d'entiers
J'ai un tableau d'entiers, permet de supposer qu'ils sont de type int64_t
. Maintenant, je sais que seul chaque premier n
bits de l'entier sont significatifs (qui est, je sais qu'ils sont limités par certaines limites).
Quel est le moyen le plus efficace pour convertir le tableau de la manière que toutes inutiles espace est supprimé (c'est à dire que j'ai le premier entier à a[0]
, le second à a[0] + n bits
et ainsi de suite) ?
Je voudrais qu'il soit général, autant que possible, parce que n
varient de temps à autre, mais je suppose qu'il pourrait être intelligent optimisations spécifiques n
comme des puissances de 2 ou qqch.
Bien sûr, je sais que je peux juste itération de la valeur sur la valeur, je veux juste vous demander StackOverflowers si vous pouvez penser de certains plus intelligente.
Edit:
Cette question n'est pas à propos de la compression de la matrice de prendre le moins d'espace possible. J'ai juste besoin de "couper" n bits
de chaque entier et compte tenu de l'éventail, je sais exactement n
de bits je peux couper.
- par curiosité, qu'avez-vous utilisé à la fin?
- Rien de vraiment, le projet était le but est mort:). Mais à partir des réponses ici et mes besoins, je finirais probablement à l'aide de quelques masques et de calcul des compensations par la main. Peut-être à l'aide de certains modèles intelligents ainsi.
- 3 ans après que vous avez demandé, j'ai enfin répondu à votre question en mettant en place un accès aléatoire conteneur dans lequel les éléments sont emballés hermétiquement. Voir ma réponse: stackoverflow.com/a/18038506/216063
Vous devez vous connecter pour publier un commentaire.
Je suis d'accord avec keraba que vous avez besoin d'utiliser quelque chose comme le codage de Huffman ou peut-être la Lempel-Ziv-Welch algorithme. Le problème avec peu d'emballage de la façon dont vous parlez, c'est que vous avez deux options:
La première option est relativement facile à mettre en œuvre, mais qui va vraiment faire perdre beaucoup d'espace, à moins que tous les entiers sont plutôt petits.
La deuxième option présente l'inconvénient majeur que vous avez à transmettre des changements dans la n d'une certaine manière dans la sortie bitstream. Par exemple, chaque valeur devra avoir une longueur associée. Cela signifie que vous êtes le stockage de deux entiers (quoique plus petit des entiers) pour chaque valeur d'entrée. Il ya une bonne chance que vous allez augmenter la taille du fichier avec cette méthode.
L'avantage de Huffman ou LZW est qu'ils créent des codes de telle façon que la longueur des codes peuvent être dérivées à partir de la sortie bitstream sans réellement le stockage de la longueur. Ces techniques permettent d'obtenir de très près à la limite de Shannon.
J'ai décidé de donner à votre idée de départ (constante n, supprimer les bits non utilisés et pack) a essayer pour le plaisir et voici l'implémentation naïve que je suis venu avec:
C'est très inefficace parce que c'est pas un peu à la fois, mais c'était la façon la plus simple à mettre en œuvre, sans aborder les questions de la endianess. Je n'ai pas testé ce soit avec un large éventail de valeurs, celles de l'essai. Aussi, il n'y a pas de vérification des limites et il est présumé que les tampons de sortie sont assez long. Donc, ce que je veux dire, c'est que ce code est probablement seulement bon pour des fins pédagogiques pour vous aider à démarrer.
Aujourd'hui j'ai sorti: PackedArray: L'Emballage Des Entiers Non Signés Étroitement (projet github).
Il met en œuvre un accès aléatoire conteneur, où les articles sont emballés au niveau des bits. En d'autres termes, il agit comme si vous étiez en mesure de manipuler un par exemple
uint9_t
ouuint17_t
tableau:La plupart de tout algorithme de compression obtiendrez proche du minimum d'entropie nécessaire pour coder les entiers, par exemple, le codage de Huffman, mais accéder à un tableau sera non négligeable.
Je sais que cela peut sembler la chose la plus évidente à dire que je suis sûr qu'il ya effectivement une solution, mais pourquoi ne pas utiliser un type plus petit, comme
uint8_t
(max 255)? ouuint16_t
(max 65535)?. Je suis sûr que vous pourriez bits-manipuler sur unint64_t
à l'aide de la définition des valeurs et de la ou des opérations similaires, mais, mis à part un exercice académique, pourquoi?Et sur la note de vue académique, Peu Se Tourner Les Hacks est une bonne lecture.
Si vous avez de taille fixe, par exemple, vous savez que votre numéro est 38bit plutôt que de 64, vous pouvez construire des structures à l'aide de bits spécifications. Amusant vous avez également des éléments plus petits pour tenir dans l'espace restant.
Ce n'est pas big/little endian sûr sans cerceau de saut, ne peut donc être utilisé à l'intérieur d'un programme plutôt que dans les données exportées au format. C'est assez souvent utilisé pour stocker des valeurs booléennes simples bits sans définir des décalages et des masques.
int[]
! Le but est d'économiser de l'espace en déplaçant des bits (peut-être) en place.Départ de Jason B de la mise en œuvre, finalement, j'ai écrit ma propre version qui traite de bits des blocs au lieu d'une seule bits. Une différence est que c'est lsb: Elle commence à partir de la plus faible en sortie des bits d'aller plus haut. Cela ne le rend plus difficile à lire, avec vidage binaire, comme Linux
xxd -b
. Comme un détail,int*
peut être trivialement changé àint64_t*
, et qu'il devrait même être mieuxunsigned
. J'ai déjà testé cette version avec quelques millions de tableaux et il semble solide, je partage donc le reste:Je ne pense pas que vous pouvez éviter une itération à travers les éléments.
Autant que je sache, le codage Huffman exige que les fréquences de "symboles", qui, sauf si vous savez les statistiques du "processus de génération de nombres entiers, vous aurez à calculer (par itération à travers chaque élément).