2009-05-05 7 views
9

Esiste una funzione in C# che prende due interi a 32 bit (int) e restituisce un singolo 64 bit (lungo)?C# - Creazione di un Int64 da due Int32

Sembra che ci dovrebbe essere un modo semplice per farlo, ma non sono riuscito a trovare una soluzione.

risposta

18

provare la seguente

public long MakeLong(int left, int right) { 
    //implicit conversion of left to a long 
    long res = left; 

    //shift the bits creating an empty space on the right 
    // ex: 0x0000CFFF becomes 0xCFFF0000 
    res = (res << 32); 

    //combine the bits on the right with the previous value 
    // ex: 0xCFFF0000 | 0x0000ABCD becomes 0xCFFFABCD 
    res = res | (long)(uint)right; //uint first to prevent loss of signed bit 

    //return the combined result 
    return res; 
} 
+0

Er, non che dovrebbe essere: long res = left; res = (res << 32) res | = destra; ritorno; ?? – ParoXoN

+0

Penso che tu intenda (ris. << 32) sopra. –

+0

grazie, anche se potresti spiegare come funziona? Mi piacerebbe capire il codice, se possibile. – DarkAmgine

5

Prova

(long)(((long)i1 << 32) | (long)i2) 

sposta il primo int data da 32 bit (la lunghezza di un int), poi RUP nella seconda int, così si finisce con i due ints concatenati insieme in un lungo.

2

Questo dovrebbe fare il trucco

((Int64) a << 32 | b) 

Dove a e b sono Int32. Anche se potresti voler controllare cosa succede con i bit più alti. O semplicemente mettilo dentro un blocco "unchecked {...}".

2

Bisogna stare attenti con un po 'di bit di questo tipo, anche se si avranno problemi con le macchine little endian/big endian (exp Le piattaforme mono non sono sempre little endian). Inoltre devi gestire l'estensione del segno. Matematicamente quanto segue è lo stesso, ma si occupa dell'estensione del segno ed è indipendente dalla piattaforma.

return (long)(high * uint.MaxValue) + low; 

Quando jitted in fase di esecuzione si tradurrà in prestazioni simili al bit twiddling. Questa è una delle cose belle delle lingue interpretate.

+0

In realtà, è necessario moltiplicare per 'uint.MaxValue + 1', cioè' 0x100000000', non '0x11111111' – Sphinxxx

6

Solo per chiarezza ... Mentre la risposta accettata sembra funzionare correttamente. Tutti i singoli rivestimenti presentati non sembrano produrre risultati accurati.

Ecco un uno di linea che fa il lavoro:

long correct = (long)left << 32 | (long)(uint)right; 

Ecco alcuni codice in modo da poter testare di persona:

long original = 1979205471486323557L; 
int left = (int)(original >> 32); 
int right = (int)(original & 0xffffffffL); 

long correct = (long)left << 32 | (long)(uint)right; 

long incorrect1 = (long)(((long)left << 32) | (long)right); 
long incorrect2 = ((Int64)left << 32 | right); 
long incorrect3 = (long)(left * uint.MaxValue) + right; 
long incorrect4 = (long)(left * 0x100000000) + right; 

Console.WriteLine(original == correct); 
Console.WriteLine(original == incorrect1); 
Console.WriteLine(original == incorrect2); 
Console.WriteLine(original == incorrect3); 
Console.WriteLine(original == incorrect4); 
Problemi correlati