Imagine dos enteros positivos A y B. Quiero combinar estos dos en un solo entero C.
No puede haber otros enteros D y E que se combinen con C. Por lo tanto, combinarlos con el operador de suma no funciona. Por ejemplo, 30 + 10 = 40 = 40 + 0 = 39 + 1 Tampoco funciona la concatenación. Por ejemplo, "31" + "2" = 312 = "3" + "12"
Esta operación de combinación también debe ser determinista (siempre produce el mismo resultado con las mismas entradas) y siempre debe producir un número entero en el lado positivo o negativo de los enteros.
10,001*A + B
?Respuestas:
Estás buscando un
NxN -> N
mapeo biyectivo . Éstos se utilizan, por ejemplo, para hacer cola de milano . Eche un vistazo a este PDF para obtener una introducción a las llamadas funciones de emparejamiento . Wikipedia presenta una función de emparejamiento específica, a saber, la función de emparejamiento de Cantor :Tres observaciones:
ZxZ -> N
mapeo biyectivo . La función de Cantor solo funciona en números no negativos. Sin embargo, esto no es un problema, porque es fácil definir una biyecciónf : Z -> N
, así:fuente
La función de emparejamiento de Cantor es realmente una de las mejores, considerando que es simple, rápida y eficiente en cuanto al espacio, pero hay algo aún mejor publicado en Wolfram por Matthew Szudzik, aquí . La limitación de la función de emparejamiento de Cantor (relativamente) es que el rango de resultados codificados no siempre se mantiene dentro de los límites de un
2N
número entero de bits si las entradas sonN
números enteros de dos bits. Es decir, si mis entradas son16
enteros de dos bits que van desde0 to 2^16 -1
, entonces hay2^16 * (2^16 -1)
combinaciones de entradas posibles, por lo que, según el Principio de Pigeonhole obvio , necesitamos una salida de tamaño al menos2^16 * (2^16 -1)
, que sea igual2^32 - 2^16
o, en otras palabras, un mapa de32
los números de bits deberían ser factibles idealmente. Esto puede no ser de poca importancia práctica en el mundo de la programación.Función de emparejamiento de Cantor :
Ingrese la función de Szudzik :
Ahora, considerando el hecho de que generalmente tratamos con implementaciones firmadas de números de varios tamaños en lenguajes / marcos, consideremos
signed 16
los enteros de bits que van desde-(2^15) to 2^15 -1
(más adelante veremos cómo extender incluso la salida para que se extienda sobre el rango firmado). Desdea
yb
tienen que ser positivos van desde0 to 2^15 - 1
.Función de emparejamiento de Cantor :
Ahora la función de Szudzik :
Consideremos los enteros negativos. Eso está más allá de la pregunta original que conozco, pero solo se elabora para ayudar a los futuros visitantes.
Función de emparejamiento de Cantor :
La función de Szudzik :
Ahora todo esto mientras que la salida siempre ha sido positiva. En el mundo firmado, se ahorrará aún más espacio si pudiéramos transferir la mitad de la salida al eje negativo . Podrías hacerlo así para Szudzik's:
Lo que hago: después de aplicar un peso de
2
a las entradas y pasar por la función, divido la salida por dos y llevo algunas de ellas al eje negativo multiplicando por-1
.Vea los resultados, para cualquier entrada en el rango de un
16
número de bit con signo , la salida se encuentra dentro de los límites de un32
entero de bit con signo que es genial. No estoy seguro de cómo hacer lo mismo para la función de emparejamiento de Cantor, pero no intenté tanto como no es tan eficiente. Además, más cálculos involucrados en la función de emparejamiento de Cantor significa que también es más lento .Aquí hay una implementación de C #.
Como los cálculos intermedios pueden exceder los límites del
2N
entero con signo, he usado el4N
tipo entero (la última división2
devuelve el resultado2N
).El enlace que he proporcionado en una solución alternativa muestra muy bien un gráfico de la función que utiliza cada punto en el espacio. ¡Es sorprendente ver que puedes codificar de forma única un par de coordenadas en un solo número de forma reversible! ¡Mundo mágico de números!
fuente
(0,0)
a través(65535,65535)
de un único número, entoncesa<<16 + b
es mejor en todos los sentidos, básicamente (más rápido, más simple, más fácil de entender, más evidente) . Si quieres(-32768,-32768)
a(327687,327687)
cambio, simplemente sujeta 32768 primero.Si A y B pueden expresarse con 2 bytes, puede combinarlos en 4 bytes. Ponga A en la mitad más significativa y B en la mitad menos significativa.
En lenguaje C esto da (suponiendo sizeof (short) = 2 y sizeof (int) = 4):
fuente
combine()
deberíareturn (unsigned short)(A<<16) | (unsigned short)(B);
Para que los números negativos se puedan empaquetar correctamente.A<<16
saldrá de los límites. Debería serreturn (unsigned int)(A<<16) | (unsigned short)(B);
¿Es esto posible?
Estás combinando dos enteros. Ambos tienen el rango de -2,147,483,648 a 2,147,483,647 pero solo tomará los positivos. Eso hace 2147483647 ^ 2 = 4,61169E + 18 combinaciones. Como cada combinación tiene que ser única Y dar como resultado un número entero, necesitará algún tipo de número entero mágico que pueda contener esta cantidad de números.
¿O es mi lógica defectuosa?
fuente
La forma matemática estándar para los enteros positivos es utilizar la singularidad de la factorización prima.
La desventaja es que la imagen tiende a abarcar una amplia gama de enteros, por lo que cuando se trata de expresar el mapeo en un algoritmo informático, puede tener problemas para elegir un tipo apropiado para el resultado.
Puede modificar esto para tratar con negativo
x
yy
codificando banderas con potencias de 5 y 7 términos.p.ej
fuente
Deje que el número
a
sea el primero,b
el segundo. Seap
ela+1
enésimo número primo,q
sea elb+1
enésimo número primoEntonces, el resultado es
pq
, sia<b,
o2pq
sia>b
. Sia=b
, que así seap^2
.fuente
No es tan difícil construir un mapeo:
Descubrir cómo obtener el valor para un arbitrario a, b es un poco más difícil.
fuente
f(a, b) = s(a+b) + a
, dóndes(n) = n*(n+1)/2
s(a+b+1)-s(a+b) = a+b+1 < a
.No entendí lo que quieres decir con:
¿Cómo puedo escribir (mayor que), (menor que) caracteres en este foro?
fuente
backtick escapes
.Aunque la respuesta de Stephan202 es la única realmente general, para los enteros en un rango acotado puede hacerlo mejor. Por ejemplo, si su rango es 0..10,000, entonces puede hacer:
Los resultados pueden caber en un solo entero para un rango hasta la raíz cuadrada de la cardinalidad del tipo entero. Esto empaca un poco más eficientemente que el método más general de Stephan202. También es considerablemente más sencillo de decodificar; que no requieren raíces cuadradas, para empezar :)
fuente
Para enteros positivos como argumentos y donde el orden de los argumentos no importa:
Aquí hay una función de emparejamiento desordenada :
Para x ≠ y, aquí hay una función de emparejamiento desordenada única :
fuente
Revisa esto: http://en.wikipedia.org/wiki/Pigeonhole_principle . Si A, B y C son del mismo tipo, no se puede hacer. Si A y B son enteros de 16 bits, y C es de 32 bits, entonces simplemente puede usar el desplazamiento.
La naturaleza misma de los algoritmos de hash es que no pueden proporcionar un hash único para cada entrada diferente.
fuente
Aquí hay una extensión del código de @DoctorJ a enteros ilimitados basado en el método proporcionado por @nawfal. Puede codificar y decodificar. Funciona con matrices normales y matrices numpy.
fuente
¿Qué tal algo mucho más simple? Dados dos números, A y B dejan que str sea la concatenación: 'A' + ';' + 'B'. Luego, deje que la salida sea hash (str). Sé que esta no es una respuesta matemática, pero un simple script de Python (que tiene una función hash incorporada) debería hacer el trabajo.
fuente
Lo que sugieres es imposible. Siempre tendrás colisiones.
Para asignar dos objetos a otro conjunto único, el conjunto asignado debe tener un tamaño mínimo del número de combinaciones esperadas:
Suponiendo un entero de 32 bits, tiene 2147483647 enteros positivos. Elegir dos de estos en los que el orden no importa y con la repetición produce 2305843008139952128 combinaciones. Esto no encaja bien en el conjunto de enteros de 32 bits.
Sin embargo, puede ajustar esta asignación en 61 bits. Usar un número entero de 64 bits es probablemente lo más fácil. Establezca la palabra alta en el entero más pequeño y la palabra baja en la más grande.
fuente
Digamos que tiene un número entero de 32 bits, ¿por qué no simplemente mueve A a la primera mitad de 16 bits y B a la otra?
Además de ser tan eficiente en espacio como sea posible y barato de calcular, un efecto secundario realmente genial es que puedes hacer cálculos vectoriales en el número empaquetado.
fuente
tengamos dos números B y C, codificándolos en un solo número A
A = B + C * N
dónde
B = A% N = B
C = A / N = C
fuente
Dados los enteros positivos A y B, supongamos que D = número de dígitos A tiene, y E = número de dígitos B tiene El resultado puede ser una concatenación de D, 0, E, 0, A y B.
Ejemplo: A = 300, B = 12. D = 3, E = 2 resultado = 302030012. Esto aprovecha el hecho de que el único número que comienza con 0, es 0,
Pro: fácil de codificar, fácil de decodificar, legible por humanos, se pueden comparar primero dígitos significativos, potencial de comparación sin cálculo, simple verificación de errores.
Contras: el tamaño de los resultados es un problema. Pero está bien, ¿por qué estamos almacenando enteros ilimitados en una computadora?
fuente
Si desea más control, como asignar bits X para el primer número e bits Y para el segundo número, puede usar este código:
Yo uso 32 bits en total. La idea aquí es que si desea, por ejemplo, que el primer número tenga hasta 10 bits y el segundo número tenga hasta 12 bits, puede hacer esto:
Ahora puede almacenar en
num_a
el número máximo que es2^10 - 1 = 1023
y en elnum_b
valor máximo de2^12 - 1 = 4095
.Para establecer el valor para num A y num B:
Ahora
bnum
es todos los bits (32 bits en total. Puede modificar el código para usar 64 bits) Para obtener num a:Para obtener num b:
EDITAR:
bnum
se puede almacenar dentro de la clase. No lo hice porque mis propias necesidades compartí el código y espero que sea útil.Gracias por la fuente: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ por la función para extraer bits y gracias también por
mouviciel
responder en esta publicación. Usando estos para las fuentes podría encontrar una solución más avanzadafuente