Mappare due numeri interi su uno, in un modo unico e deterministico


235

Immagina due numeri interi positivi A e B. Voglio combinare questi due in un singolo numero intero C.

Non ci possono essere altri numeri interi D ed E che si combinano con C. Quindi la loro combinazione con l'operatore addizione non funziona. Ad esempio 30 + 10 = 40 = 40 + 0 = 39 + 1 Né la concaturazione funziona. Ad esempio "31" + "2" = 312 = "3" + "12"

Questa operazione di combinazione dovrebbe anche essere deterministica (produce sempre lo stesso risultato con gli stessi input) e dovrebbe sempre produrre un numero intero sul lato positivo o negativo degli interi.


10
Dovresti chiarire se intendi numeri interi nel software o numeri interi in matematica. Nel software, scegli qualsiasi tipo intero e avrà una dimensione, quindi ne avrai un numero finito, quindi non esiste una soluzione (a meno che, naturalmente, i tuoi dati di input non siano garantiti all'interno di un intervallo e il tuo output può essere qualsiasi numero intero). In matematica vedi la soluzione di ASK.
Daniel Daranas,

Sto parlando di numeri interi limitati in un intervallo basso e positivo. Di 'da 0 a 10.000
danneggia

27
@harm: Allora che ne dici di solo 10,001*A + B?
BlueRaja - Danny Pflughoeft,

2
Ho trovato queste funzioni PHP: gist.github.com/hannesl/8031402
cakan

Se l'ordine non ha importanza, ad esempio: (3,12) e (12,3) danno lo stesso risultato, utilizzo "A + B" + "A * B"
Sodj

Risposte:


233

Stai cercando una NxN -> Nmappatura biiettiva . Questi sono usati per esempio a coda di rondine . Dai un'occhiata a questo PDF per un'introduzione alle cosiddette funzioni di associazione . Wikipedia introduce una funzione di associazione specifica, ovvero la funzione di associazione Cantor :

pi (k1, k2) = 1/2 (k1 + k2) (k1 + k2 + 1) + k2

Tre osservazioni:

  • Come altri hanno chiarito, se hai intenzione di implementare una funzione di associazione, potresti presto scoprire che hai bisogno di interi (bignum) arbitrariamente grandi.
  • Se non si desidera fare una distinzione tra le coppie (a, b) e (b, a), quindi ordinare aeb prima di applicare la funzione di associazione.
  • In realtà ho mentito. Stai cercando una ZxZ -> Nmappatura biiettiva . La funzione di Cantor funziona solo su numeri non negativi. Questo non è comunque un problema, perché è facile definire una biiezionef : Z -> N , in questo modo:
    • f (n) = n * 2 se n> = 0
    • f (n) = -n * 2 - 1 se n <0

13
+1 Penso che questa sia la risposta corretta per numeri interi illimitati.
Sconosciuto

4
Come posso ottenere di nuovo il valore di k1, k2?
MinuMaster,

3
@MinuMaster: che è descritto nello stesso articolo di Wikipedia, in Inversione della funzione di associazione Cantor .
Stephan202,

4
Vedi anche la funzione di Szudzik, spiegata da Newfal di seguito.
OliJG il

1
Sebbene ciò sia corretto per numeri interi non limitati, non è ottimale per numeri interi limitati. Penso che il commento di @ blue-raja abbia di gran lunga più senso.
Kardasis,

226

La funzione di accoppiamento Cantor è davvero una delle migliori là fuori considerando la sua semplicità, rapidità ed efficienza dello spazio, ma c'è qualcosa di ancora meglio pubblicato su Wolfram da Matthew Szudzik, qui . Il limite della funzione di accoppiamento Cantor (relativamente) è che l'intervallo dei risultati codificati non rimane sempre entro i limiti di un 2Nnumero intero di bit se gli ingressi sono Nnumeri interi di due bit. Cioè, se i miei input sono 16numeri interi a due bit che vanno da 0 to 2^16 -1allora, allora ci sono 2^16 * (2^16 -1)combinazioni di input possibili, quindi dall'ovvio Principio di Pigeonhole , abbiamo bisogno di un output di dimensioni almeno numeri di bit dovrebbero essere idealmente fattibili. Questo potrebbe non avere poca importanza pratica nel mondo della programmazione.2^16 * (2^16 -1) , che è uguale 2^32 - 2^16o, in altre parole, una mappa di32

Funzione di abbinamento Cantor :

(a + b) * (a + b + 1) / 2 + a; where a, b >= 0

La mappatura per due numeri massimi al massimo di 16 bit (65535, 65535) sarà 8589803520 che, come vedi, non può essere adattato a 32 bit.

Inserisci la funzione di Szudzik :

a >= b ? a * a + a + b : a + b * b;  where a, b >= 0

Il mapping per (65535, 65535) sarà ora 4294967295 che, come vedi, è un numero intero a 32 bit (da 0 a 2 ^ 32 -1). È qui che questa soluzione è ideale, utilizza semplicemente ogni singolo punto in quello spazio, quindi nulla può ottenere uno spazio più efficiente.


Ora considerando il fatto che in genere trattiamo le implementazioni firmate di numeri di varie dimensioni in linguaggi / framework, consideriamo gli signed 16interi di bit che vanno da -(2^15) to 2^15 -1(in seguito vedremo come estendere anche l'output per estendere l'intervallo firmato). Dal momento che ae bdevono essere positivi vanno da 0 to 2^15 - 1.

Funzione di abbinamento Cantor :

La mappatura per due numeri interi con segno massimo a 16 bit (32767, 32767) sarà 2147418112 che è appena al di sotto del valore massimo per numero intero a 32 bit con segno.

Ora la funzione di Szudzik :

(32767, 32767) => 1073741823, molto più piccolo ..

Consideriamo gli interi negativi. Questo è al di là della domanda originale che conosco, ma solo elaborando per aiutare i futuri visitatori.

Funzione di abbinamento Cantor :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
(A + B) * (A + B + 1) / 2 + A;

(-32768, -32768) => 8589803520 che è Int64. L'uscita a 64 bit per gli ingressi a 16 bit potrebbe essere così imperdonabile !!

La funzione di Szudzik :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
A >= B ? A * A + A + B : A + B * B;

(-32768, -32768) => 4294967295 che è 32 bit per l'intervallo senza segno o 64 bit per l'intervallo con segno, ma ancora meglio.

Ora tutto questo mentre l'output è sempre stato positivo. Nel mondo firmato, sarà ancora più salvaspazio se potessimo trasferire metà dell'output sull'asse negativo . Potresti farlo in questo modo per Szudzik:

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
C = (A >= B ? A * A + A + B : A + B * B) / 2;
a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;

(-32768, 32767) => -2147483648

(32767, -32768) => -2147450880

(0, 0) => 0 

(32767, 32767) => 2147418112

(-32768, -32768) => 2147483647

Cosa faccio: dopo aver applicato un peso 2sugli ingressi e aver esaminato la funzione, allora divido l'output per due e ne porto alcuni sull'asse negativo moltiplicando per -1.

Vedere i risultati, per qualsiasi input nell'intervallo di un 16numero di bit con segno, l'output rientra nei limiti di un segno32 numero intero di bit con segno che è interessante. Non sono sicuro di come procedere allo stesso modo per la funzione di abbinamento Cantor ma non ho provato tanto quanto non è efficiente. Inoltre, un numero maggiore di calcoli coinvolti nella funzione di accoppiamento Cantor significa anche che è più lento .

Ecco un'implementazione in C #.

public static long PerfectlyHashThem(int a, int b)
{
    var A = (ulong)(a >= 0 ? 2 * (long)a : -2 * (long)a - 1);
    var B = (ulong)(b >= 0 ? 2 * (long)b : -2 * (long)b - 1);
    var C = (long)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

public static int PerfectlyHashThem(short a, short b)
{
    var A = (uint)(a >= 0 ? 2 * a : -2 * a - 1);
    var B = (uint)(b >= 0 ? 2 * b : -2 * b - 1);
    var C = (int)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

Poiché i calcoli intermedi possono superare i limiti di 2Nnumeri interi con segno, ho usato il 4Ntipo intero (l'ultima divisione per2 riporta il risultato a 2N).

Il collegamento che ho fornito su una soluzione alternativa descrive bene un grafico della funzione che utilizza ogni singolo punto nello spazio. È incredibile vedere che potresti codificare in modo univoco una coppia di coordinate in un singolo numero in modo reversibile! Magico mondo dei numeri !!


5
Quale sarebbe la funzione unhash modificata per gli interi con segno?
Arets Paeglis,

7
Questa risposta mi confonde. Se vuoi mappare (0,0)attraverso (65535,65535)un singolo numero, allora a<<16 + bè meglio praticamente in ogni modo (più veloce, più semplice, più facile da capire, più ovvio) . Se si vuole (-32768,-32768)a (327687,327687)posto, solo soggetto 32768 prima.
BlueRaja - Danny Pflughoeft,

2
@ BlueRaja-DannyPflughoeft hai ragione. La mia risposta sarebbe valida se l'intervallo non è limitato o sconosciuto. Lo aggiornerò. L'avevo scritto prima che il limite mi importasse. La modifica di questa risposta è stata a lungo nella mia mente. Presto troverò tempo.
nawfal,

La funzione di Szudzik funziona per combinazioni o permutazioni. Sembra essere permutazioni giusto? Se voglio usare Combination posso semplicemente eliminare le parti IF ed Else dell'algoritmo?
Jamie Marshall,

Ecco un'implementazione Python della funzione di Szudzik generalizzata a tuple di qualsiasi lunghezza: gitlab.com/snippets/32559
Doctor J

47

Se A e B possono essere espressi con 2 byte, è possibile combinarli su 4 byte. Metti A sulla metà più significativa e B sulla metà meno significativa.

Nel linguaggio C questo dà (assumendo sizeof (short) = 2 e sizeof (int) = 4):

int combine(short A, short B)
{
    return A<<16 | B;
}

short getA(int C)
{
    return C>>16;
}

short getB(int C)
{
    return C & 0xFFFF;
}

3
combine()dovrebbe In return (unsigned short)(A<<16) | (unsigned short)(B); modo che i numeri negativi possano essere impacchettati correttamente.
Andy,

2
@Andy A<<16andrà fuori dai limiti. Dovrebbe esserereturn (unsigned int)(A<<16) | (unsigned short)(B);
DanSkeel

15

È possibile?
Stai combinando due numeri interi. Entrambi hanno un intervallo compreso tra -2.147.483.648 e 2.147.483.647 ma prenderai solo gli aspetti positivi. Ciò rende 2147483647 ^ 2 = 4.61169E + 18 combinazioni. Poiché ogni combinazione deve essere univoca E comportare un numero intero, avrai bisogno di un qualche tipo di numero magico che possa contenere questa quantità di numeri.

O la mia logica è difettosa?


+1 È quello che penso anch'io (anche se ho fatto il calcolo dicendo che l'ordine di A e B non ha importanza)
lc.

4
Sì, la tua logica è corretta secondo il principio del buco del piccione. Purtroppo il richiedente non ha specificato se il numero intero è limitato o meno.
Sconosciuto

Sì, ho avuto anche quel ripensamento, ma ho pensato che il messaggio fosse essenzialmente lo stesso, quindi non mi sono preoccupato di ripetere la ricomposizione.
Boris Callens,

Inoltre mi sono appena reso conto che avrei dovuto riprendere i miei libri di testo per il calcolo delle probabilità (traduzione letterale dall'olandese).
Boris Callens,

2
@Boris: Kansrekening è "teoria della probabilità".
Stephan202,

8

Il metodo matematico standard per numeri interi positivi consiste nell'utilizzare l'unicità della fattorizzazione in fattori primi.

f( x, y ) -> 2^x * 3^y

Il rovescio della medaglia è che l'immagine tende a coprire una gamma piuttosto ampia di numeri interi, quindi quando si tratta di esprimere la mappatura in un algoritmo informatico, si potrebbero avere problemi con la scelta di un tipo appropriato per il risultato.

Puoi modificarlo per gestire il negativo xe ycodificando un flag con poteri di 5 e 7 termini.

per esempio

f( x, y ) -> 2^|x| * 3^|y| * 5^(x<0) * 7^(y<0)

La matematica va bene. Ma, come dice Boris, se si desidera eseguire questo come programma per computer, è necessario tenere conto della finezza della macchina. L'algoritmo funzionerà correttamente per un sottoinsieme di numeri interi rappresentabili nella relativa macchina.
Yuval F,

2
L'ho affermato nel mio secondo paragrafo. I tag sulla domanda indicano "algoritmo", "matematico" e "deterministico", non un linguaggio particolare. L'intervallo di input potrebbe non essere limitato e l'ambiente potrebbe avere un tipo intero senza limiti 'bigint'.
CB Bailey,

8

Lascia che il numero asia il primo, bil secondo. Sia pil a+1numero primo, qsia il b+1numero primo

Quindi, il risultato è pq, se a<b,o 2pqse a>b. Se a=b, lascia che sia p^2.


4
Dubito che vorresti una soluzione NP.
user44242,

1
Questo non produce lo stesso risultato per a = 5, b = 14 e a = 6, b = 15?
Lieven Keersmaekers,

3
Due prodotti di due numeri primi diversi non possono avere lo stesso risultato (decomposizione unica del fattore primo) a = 5, b = 14 -> il risultato è 13 * 47 = 611 a = 6, b = 15 -> il risultato è 17 * 53 = 901
Chiedi

4

Costruire una mappatura non è poi così difficile:

   1 2 3 4 5 usa questa mappatura se (a, b)! = (B, a)
1 0 1 3 6 10
2 2 4 7 11 16
3 5 8 12 17 23
4 9 13 18 24 31
5 14 19 25 32 40

   1 2 3 4 5 usa questa mappatura se (a, b) == (b, a) (mirror)
1 0 1 2 4 6
2 1 3 5 7 10
3 2 5 8 11 14
4 4 8 11 15 19
5 6 10 14 19 24


    0 1 -1 2 -2 usalo se hai bisogno di negativo / positivo
 0 0 1 2 4 6
 1 1 3 5 7 10
-1 2 5 8 11 14
 2 4 8 11 15 19
-2 6 10 14 19 24

Capire come ottenere il valore per un a arbitrario a, b è un po 'più difficile.


4

f(a, b) = s(a+b) + a, dove s(n) = n*(n+1)/2

  • Questa è una funzione: è deterministica.
  • È anche iniettivo - f mappa valori diversi per coppie diverse (a, b). È possibile dimostrare questo con il fatto: s(a+b+1)-s(a+b) = a+b+1 < a.
  • Restituisce valori abbastanza piccoli - buono se lo userete per l'indicizzazione dell'array, poiché l'array non deve essere grande.
  • È adatto alla cache - se due coppie (a, b) sono vicine tra loro, quindi f mappa i numeri vicini tra loro (rispetto ad altri metodi).

Non ho capito cosa intendi per:

dovrebbe sempre produrre un numero intero sul lato positivo o negativo degli interi

Come posso scrivere (maggiore di), (minore di) caratteri in questo forum?


2
Maggiore e minore di caratteri dovrebbero funzionare bene all'interno backtick escapes.
TRiG

Ciò equivale alla funzione di accoppiamento Cantor e come tale non funziona con numeri interi negativi.
Assapora Josipovic

4

Sebbene la risposta di Stephan202 sia l'unica veramente generale, per gli interi in un intervallo limitato puoi fare di meglio. Ad esempio, se il tuo intervallo è 0..10.000, puoi fare:

#define RANGE_MIN 0
#define RANGE_MAX 10000

unsigned int merge(unsigned int x, unsigned int y)
{
    return (x * (RANGE_MAX - RANGE_MIN + 1)) + y;
}

void split(unsigned int v, unsigned int &x, unsigned int &y)
{
    x = RANGE_MIN + (v / (RANGE_MAX - RANGE_MIN + 1));
    y = RANGE_MIN + (v % (RANGE_MAX - RANGE_MIN + 1));
}

I risultati possono rientrare in un singolo numero intero per un intervallo fino alla radice quadrata della cardinalità del tipo intero. Questo è leggermente più efficiente rispetto al metodo più generale di Stephan202. È anche molto più semplice decodificare; non richiede radici quadrate, per cominciare :)


Questo è forse possibile per i galleggianti?
Lukas,


3

Controlla questo: http://en.wikipedia.org/wiki/Pigeonhole_principle . Se A, B e C sono dello stesso tipo, non è possibile farlo. Se A e B sono numeri interi a 16 bit e C è a 32 bit, è possibile utilizzare semplicemente lo spostamento.

La natura stessa degli algoritmi di hashing è che non possono fornire un hash univoco per ogni input diverso.


2

Ecco un'estensione del codice di @DoctorJ a numeri interi non associati in base al metodo fornito da @nawfal. Può codificare e decodificare. Funziona con array normali e array intorpiditi.

#!/usr/bin/env python
from numbers import Integral    

def tuple_to_int(tup):
    """:Return: the unique non-negative integer encoding of a tuple of non-negative integers."""
    if len(tup) == 0:  # normally do if not tup, but doesn't work with np
        raise ValueError('Cannot encode empty tuple')
    if len(tup) == 1:
        x = tup[0]
        if not isinstance(x, Integral):
            raise ValueError('Can only encode integers')
        return x
    elif len(tup) == 2:
        # print("len=2")
        x, y = tuple_to_int(tup[0:1]), tuple_to_int(tup[1:2])  # Just to validate x and y

        X = 2 * x if x >= 0 else -2 * x - 1  # map x to positive integers
        Y = 2 * y if y >= 0 else -2 * y - 1  # map y to positive integers
        Z = (X * X + X + Y) if X >= Y else (X + Y * Y)  # encode

        # Map evens onto positives
        if (x >= 0 and y >= 0):
            return Z // 2
        elif (x < 0 and y >= 0 and X >= Y):
            return Z // 2
        elif (x < 0 and y < 0 and X < Y):
            return Z // 2
        # Map odds onto negative
        else:
            return (-Z - 1) // 2
    else:
        return tuple_to_int((tuple_to_int(tup[:2]),) + tuple(tup[2:]))  # ***speed up tuple(tup[2:])?***


def int_to_tuple(num, size=2):
    """:Return: the unique tuple of length `size` that encodes to `num`."""
    if not isinstance(num, Integral):
        raise ValueError('Can only encode integers (got {})'.format(num))
    if not isinstance(size, Integral) or size < 1:
        raise ValueError('Tuple is the wrong size ({})'.format(size))
    if size == 1:
        return (num,)
    elif size == 2:

        # Mapping onto positive integers
        Z = -2 * num - 1 if num < 0 else 2 * num

        # Reversing Pairing
        s = isqrt(Z)
        if Z - s * s < s:
            X, Y = Z - s * s, s
        else:
            X, Y = s, Z - s * s - s

        # Undoing mappint to positive integers
        x = (X + 1) // -2 if X % 2 else X // 2  # True if X not divisible by 2
        y = (Y + 1) // -2 if Y % 2 else Y // 2  # True if Y not divisible by 2

        return x, y

    else:
        x, y = int_to_tuple(num, 2)
        return int_to_tuple(x, size - 1) + (y,)


def isqrt(n):
    """":Return: the largest integer x for which x * x does not exceed n."""
    # Newton's method, via http://stackoverflow.com/a/15391420
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

2

Che ne dici di qualcosa di molto più semplice: dati due numeri, A e B lasciano che str sia la concatenazione: 'A' + ';' + 'B'. Quindi lascia che l'output sia hash (str). So che questa non è una risposta matematica, ma un semplice script Python (che ha una funzione hash integrata) dovrebbe fare il lavoro.


2
ma (8,11) e (81,1) sono associati allo stesso numero 811
Leevi L

Questo è un buon punto. Puoi risolvere quel problema semplicemente aggiungendo un simbolo nel mezzo. Quindi per (8, 11) hash la stringa "8-11" e per (81, 1) hash la stringa "81-1". Quindi in generale per (A, B) hash la stringa "AB". (So ​​che sembra confuso, ma dovrebbe funzionare).
Madhav Nakar,

è anche sbagliato perché quel compito è mappare due numeri interi su un nuovo numero intero, non una stringa con un simbolo
Leevi L

Vengo da una prospettiva CS piuttosto che matematica (per le soluzioni matematiche guarda le risposte sopra). Sto prendendo due numeri interi, trasformandoli in una stringa, quando poi viene trasformato in un numero intero. In sostanza, sì, sto mappando due numeri interi su uno nuovo.
Madhav Nakar,

1

Quello che suggerisci è impossibile. Avrai sempre delle collisioni.

Per mappare due oggetti su un altro singolo set, il set mappato deve avere una dimensione minima del numero di combinazioni previste:

Supponendo un numero intero a 32 bit, hai 2147483647 numeri interi positivi. Scegliere due di questi in cui l'ordine non ha importanza e con la ripetizione produce combinazioni di 2305843008139952128. Questo non si adatta bene all'insieme di numeri interi a 32 bit.

Tuttavia, è possibile adattare questa mappatura a 61 bit. L'uso di un numero intero a 64 bit è probabilmente il più semplice. Imposta la parola alta sull'intero più piccolo e la parola bassa su quella più grande.


1

Supponi di avere un numero intero a 32 bit, perché non spostare semplicemente A nella prima metà a 16 bit e B nell'altra?

def vec_pack(vec):
    return vec[0] + vec[1] * 65536;


def vec_unpack(number):
    return [number % 65536, number // 65536];

Oltre a essere il più efficiente possibile nello spazio ed economico da calcolare, un effetto collaterale davvero interessante è che puoi fare matematica vettoriale sul numero impaccato.

a = vec_pack([2,4])
b = vec_pack([1,2])

print(vec_unpack(a+b)) # [3, 6] Vector addition
print(vec_unpack(a-b)) # [1, 2] Vector subtraction
print(vec_unpack(a*2)) # [4, 8] Scalar multiplication

0

cerchiamo di avere due numeri B e C, codificandoli in un unico numero A

A = B + C * N

dove

B = A% N = B

C = A / N = C


2
Come scegli N per rendere unica questa rappresentazione? Se risolvi questo problema, in che modo questa risposta è diversa da quelle sopra?
Prugna

Dovresti aggiungere che N deve essere maggiore sia di B che di C.
Radoslav Stoyanov il

0

Dati gli interi positivi A e B, sia D = numero di cifre che A ha, ed E = numero di cifre che B ha Il risultato può essere una concatenazione di D, 0, E, 0, A e B.

Esempio: A = 300, B = 12. D = 3, E = 2 risultato = 302030012. Questo sfrutta il fatto che l'unico numero che inizia con 0, è 0,

Pro: facile da codificare, facile da decodificare, leggibile dall'uomo, cifre significative possono essere confrontate per prime, possibilità di confronto senza calcolo, semplice controllo degli errori.

Contro: la dimensione dei risultati è un problema. Ma va bene, perché stiamo comunque memorizzando numeri interi senza limiti in un computer.


0

Se si desidera un maggiore controllo, ad esempio allocare bit X per il primo numero e bit Y per il secondo numero, è possibile utilizzare questo codice:

class NumsCombiner
{

    int num_a_bits_size;
    int num_b_bits_size;

    int BitsExtract(int number, int k, int p)
    {
        return (((1 << k) - 1) & (number >> (p - 1)));
    }

public:
    NumsCombiner(int num_a_bits_size, int num_b_bits_size)
    {
        this->num_a_bits_size = num_a_bits_size;
        this->num_b_bits_size = num_b_bits_size;
    }

    int StoreAB(int num_a, int num_b)
    {
        return (num_b << num_a_bits_size) | num_a;
    }

    int GetNumA(int bnum)
    {
        return BitsExtract(bnum, num_a_bits_size, 1);
    }

    int GetNumB(int bnum)
    {
        return BitsExtract(bnum, num_b_bits_size, num_a_bits_size + 1);
    }
};

Uso 32 bit in totale. L'idea qui è che se si desidera ad esempio che il primo numero sarà fino a 10 bit e il secondo numero sarà fino a 12 bit, è possibile farlo:

NumsCombiner nums_mapper(10/*bits for first number*/, 12/*bits for second number*/);

Ora puoi memorizzare num_ail numero massimo che è 2^10 - 1 = 1023e nel num_bvalore massimo di2^12 - 1 = 4095 .

Per impostare il valore per num A e num B:

int bnum = nums_mapper.StoreAB(10/*value for a*/, 12 /*value from b*/);

Ora bnumsono tutti i bit (32 bit in totale. È possibile modificare il codice per utilizzare 64 bit) Per ottenere num a:

int a = nums_mapper.GetNumA(bnum);

Per ottenere il numero b:

int b = nums_mapper.GetNumB(bnum);

EDIT: bnumpuò essere memorizzato all'interno della classe. Non l'ho fatto perché le mie esigenze hanno condiviso il codice e spero che possa essere utile.

Grazie per la fonte: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ per la funzione di estrazione dei bit e grazie anche per la mouvicielrisposta in questo post. Usando questi per le fonti ho potuto trovare una soluzione più avanzata

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.