Imaginez deux entiers positifs A et B. Je veux combiner ces deux en un seul entier C.
Il ne peut pas y avoir d'autres entiers D et E qui se combinent en C. Donc, les combiner avec l'opérateur d'addition ne fonctionne pas. Par exemple 30 + 10 = 40 = 40 + 0 = 39 + 1 La concatination ne fonctionne pas non plus. Par exemple "31" + "2" = 312 = "3" + "12"
Cette opération de combinaison doit également être déterministe (toujours produire le même résultat avec les mêmes entrées) et doit toujours produire un entier du côté positif ou négatif des nombres entiers.
10,001*A + B
?Réponses:
Vous recherchez une
NxN -> N
cartographie bijective . Ceux-ci sont utilisés par exemple pour la queue d'aronde . Jetez un œil à ce PDF pour une introduction aux fonctions dites de couplage . Wikipedia introduit une fonction d'appariement spécifique, à savoir la fonction d'appariement Cantor :Trois remarques:
ZxZ -> N
cartographie bijective . La fonction de Cantor ne fonctionne que sur les nombres non négatifs. Ce n'est pas un problème cependant, car il est facile de définir une bijectionf : Z -> N
, comme ceci:la source
La fonction de couplage de Cantor est vraiment l'une des meilleures là-bas compte tenu de sa simplicité, de sa rapidité et de son faible encombrement, mais il y a quelque chose de mieux publié à Wolfram par Matthew Szudzik, ici . La limitation de la fonction d'appariement de Cantor (relativement) est que la plage de résultats codés ne reste pas toujours dans les limites d'un
2N
entier de bits si les entrées sontN
des entiers de deux bits. Autrement dit, si mes entrées sont16
des entiers de deux bits allant de0 to 2^16 -1
, alors il y a des2^16 * (2^16 -1)
combinaisons d'entrées possibles, donc par le principe évident de Pigeonhole , nous avons besoin d'une sortie de taille au moins2^16 * (2^16 -1)
, qui est égale2^32 - 2^16
, ou en d'autres termes, une carte de32
les nombres de bits devraient être réalisables idéalement. Cela peut ne pas être de peu d'importance pratique dans le monde de la programmation.Fonction d'appariement Cantor :
Entrez dans la fonction de Szudzik :
Considérant maintenant le fait que nous traitons généralement les implémentations signées de nombres de différentes tailles dans les langages / frameworks, considérons
signed 16
les entiers binaires allant de-(2^15) to 2^15 -1
(plus tard, nous verrons comment étendre même la sortie pour s'étendre sur la plage signée). Depuisa
etb
doivent être positifs, ils vont de0 to 2^15 - 1
.Fonction d'appariement Cantor :
Maintenant la fonction de Szudzik :
Prenons les entiers négatifs. C'est au-delà de la question d'origine que je connais, mais juste pour élaborer pour aider les futurs visiteurs.
Fonction d'appariement Cantor :
La fonction de Szudzik :
Maintenant, tout cela alors que la sortie a toujours été positive. Dans le monde signé, ce sera encore plus d'économie d'espace si nous pouvions transférer la moitié de la sortie sur l'axe négatif . Vous pouvez le faire comme ceci pour Szudzik:
Ce que je fais: Après avoir appliqué un poids de
2
aux entrées et avoir parcouru la fonction, je divise ensuite la sortie par deux et amène certaines d'entre elles à l'axe négatif en multipliant par-1
.Voir les résultats, pour toute entrée dans la plage d'un
16
nombre de bits signé , la sortie se situe dans les limites d'un32
entier de bit signé qui est cool. Je ne sais pas comment procéder de la même manière pour la fonction d'appariement Cantor, mais je n'ai pas essayé autant que ce n'est pas aussi efficace. De plus, plus de calculs impliqués dans la fonction d'appariement de Cantor signifient qu'elle est aussi plus lente .Voici une implémentation C #.
Étant donné que les calculs intermédiaires peuvent dépasser les limites de l'
2N
entier signé, j'ai utilisé le4N
type entier (la dernière division par2
ramène le résultat à2N
).Le lien que j'ai fourni sur une solution alternative représente bien un graphique de la fonction utilisant chaque point dans l'espace. C'est incroyable de voir que vous pouvez coder de manière unique une paire de coordonnées en un seul numéro de manière réversible! Monde magique des nombres !!
la source
(0,0)
travers(65535,65535)
un seul numéro,a<<16 + b
c'est mieux dans tous les sens (plus rapide, plus simple, plus facile à comprendre, plus évident) . Si tu veux(-32768,-32768)
à la(327687,327687)
place, juste sous 32768 premier.Si A et B peuvent être exprimés avec 2 octets, vous pouvez les combiner sur 4 octets. Mettez A sur la moitié la plus significative et B sur la moitié la moins significative.
En langage C, cela donne (en supposant que sizeof (short) = 2 et sizeof (int) = 4):
la source
combine()
devraitreturn (unsigned short)(A<<16) | (unsigned short)(B);
Pour que les nombres négatifs puissent être correctement emballés.A<<16
sortira des limites. Cela devrait êtrereturn (unsigned int)(A<<16) | (unsigned short)(B);
Est-ce seulement possible?
Vous combinez deux entiers. Ils ont tous deux la plage -2 147 483 648 à 2 147 483 647 mais vous ne prendrez que les positifs. Cela fait 2147483647 ^ 2 = 4,61169E + 18 combinaisons. Étant donné que chaque combinaison doit être unique ET entraîner un entier, vous aurez besoin d'une sorte d'entier magique qui peut contenir cette quantité de nombres.
Ou ma logique est-elle défectueuse?
la source
La méthode mathématique standard pour les entiers positifs consiste à utiliser l'unicité de la factorisation principale.
L'inconvénient est que l'image a tendance à s'étendre sur une assez large gamme d'entiers, donc quand il s'agit d'exprimer le mappage dans un algorithme informatique, vous pouvez avoir des problèmes avec le choix d'un type approprié pour le résultat.
Vous pouvez le modifier pour gérer le négatif
x
ety
en encodant des drapeaux avec des pouvoirs de 5 et 7 termes.par exemple
la source
Soit le nombre
a
le premier,b
le second. Soitp
lea+1
-ième nombre premier,q
soit leb+1
-ième nombre premierEnsuite, le résultat est
pq
, sia<b,
ou2pq
sia>b
. Sia=b
, que ce soitp^2
.la source
Ce n'est pas si difficile de construire une cartographie:
Trouver comment obtenir la valeur d'un arbitraire a, b est un peu plus difficile.
la source
f(a, b) = s(a+b) + a
, oùs(n) = n*(n+1)/2
s(a+b+1)-s(a+b) = a+b+1 < a
.Je n'ai pas compris ce que vous entendez par:
Comment puis-je écrire (supérieur à), (inférieur à) des caractères dans ce forum?
la source
backtick escapes
.Bien que la réponse de Stephan202 soit la seule vraiment générale, pour les entiers dans une plage bornée, vous pouvez faire mieux. Par exemple, si votre plage est de 0 à 10 000, vous pouvez faire:
Les résultats peuvent tenir dans un seul entier pour une plage allant jusqu'à la racine carrée de la cardinalité du type entier. Cela s'emballe légèrement plus efficacement que la méthode plus générale de Stephan202. Il est également beaucoup plus simple à décoder; ne nécessitant pas de racines carrées, pour commencer :)
la source
Pour les entiers positifs comme arguments et où l'ordre des arguments n'a pas d'importance:
Voici une fonction d'appariement non ordonnée :
Pour x ≠ y, voici une fonction d'appariement unique non ordonnée :
la source
Vérifiez ceci: http://en.wikipedia.org/wiki/Pigeonhole_principle . Si A, B et C sont du même type, cela ne peut pas être fait. Si A et B sont des entiers 16 bits et C est 32 bits, vous pouvez simplement utiliser le décalage.
La nature même des algorithmes de hachage est qu'ils ne peuvent pas fournir un hachage unique pour chaque entrée différente.
la source
Voici une extension du code de @DoctorJ aux entiers illimités basés sur la méthode donnée par @nawfal. Il peut encoder et décoder. Il fonctionne avec des tableaux normaux et des tableaux numpy.
la source
Que diriez-vous de quelque chose de beaucoup plus simple: étant donné deux nombres, A et B soit str la concaténation: 'A' + ';' + 'B'. Ensuite, laissez la sortie être hachée (str). Je sais que ce n'est pas une réponse mathématique, mais un simple script python (qui a une fonction de hachage intégrée) devrait faire le travail.
la source
Ce que vous proposez est impossible. Vous aurez toujours des collisions.
Afin de mapper deux objets à un autre ensemble unique, l'ensemble mappé doit avoir une taille minimale du nombre de combinaisons attendues:
En supposant un entier 32 bits, vous avez 2147483647 entiers positifs. Le choix de deux d'entre eux où l'ordre n'a pas d'importance et avec répétition donne 2305843008139952128 combinaisons. Cela ne rentre pas bien dans l'ensemble des entiers 32 bits.
Vous pouvez cependant adapter ce mappage en 61 bits. L'utilisation d'un entier 64 bits est probablement la plus simple. Définissez le mot haut sur le plus petit entier et le mot bas sur le plus grand.
la source
Disons que vous avez un entier de 32 bits, pourquoi ne pas simplement déplacer A dans la première moitié de 16 bits et B dans l'autre?
En plus d'être aussi économe en espace que possible et peu coûteux à calculer, un effet secondaire vraiment cool est que vous pouvez faire des calculs vectoriels sur le nombre emballé.
la source
ayons deux nombres B et C, en les codant en un seul nombre A
A = B + C * N
où
B = A% N = B
C = A / N = C
la source
Étant donné les entiers positifs A et B, soit D = nombre de chiffres A a, et E = nombre de chiffres B a Le résultat peut être une concaténation de D, 0, E, 0, A et B.
Exemple: A = 300, B = 12. D = 3, E = 2 résultat = 302030012. Cela profite du fait que le seul nombre commençant par 0 est 0,
Pro: Facile à coder, facile à décoder, lisible par l'homme, les chiffres significatifs peuvent être comparés en premier, potentiel de comparaison sans calcul, vérification simple des erreurs.
Inconvénients: la taille des résultats est un problème. Mais ça va, pourquoi stockons-nous de toute façon des entiers illimités dans un ordinateur.
la source
Si vous voulez plus de contrôle, comme allouer X bits pour le premier nombre et Y bits pour le deuxième nombre, vous pouvez utiliser ce code:
J'utilise 32 bits au total. L'idée ici est que si vous voulez par exemple que le premier nombre soit jusqu'à 10 bits et le second nombre jusqu'à 12 bits, vous pouvez le faire:
Vous pouvez maintenant stocker
num_a
le nombre maximal qui est2^10 - 1 = 1023
et lanum_b
valeur maximale de2^12 - 1 = 4095
.Pour définir la valeur de num A et num B:
Maintenant,
bnum
c'est tous les bits (32 bits au total. Vous pouvez modifier le code pour utiliser 64 bits) Pour obtenir num a:Pour obtenir num b:
EDIT:
bnum
peut être stocké dans la classe. Je ne l'ai pas fait parce que mes propres besoins, j'ai partagé le code et j'espère qu'il sera utile.Merci pour la source: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ pour la fonction d'extraire des bits et merci également de
mouviciel
répondre dans cet article. En utilisant ces sources, je pourrais trouver une solution plus avancéela source