2009-05-05 8 views
9

¿Hay una función en C# que tome dos enteros de 32 bits (int) y devuelva uno solo de 64 bits uno (largo)?C# - Hacer un Int64 desde dos Int32s

Parece que debería haber una manera simple de hacerlo, pero no pude encontrar una solución.

Respuesta

18

pruebe los siguientes

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, ¿No debería ser: res larga = izquierda; res = (res << 32) res | = right; return res; ?? – ParoXoN

+0

Creo que te refieres a (res << 32) arriba. –

+0

gracias, ¿pero podría explicarme cómo funciona esto? Me gustaría entender el código si es posible. – DarkAmgine

5

Trate

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

Esto desplaza la primera int dada por 32 bits (la longitud de un int), entonces RUP en la segunda int, por lo que terminan con los dos enteros concatenados juntos en un largo.

2

Esto debería hacer el truco

((Int64) a << 32 | b) 

Dónde a y b son Int32. Aunque es posible que desee comprobar lo que sucede con los bits más altos. O simplemente colóquelo dentro de un bloque "unchecked {...}".

2

Tengo que ser cuidadoso con este tipo de movimientos, porque tendrás problemas con las pequeñas máquinas endian/big endian (las plataformas exp Mono no siempre son pequeñas). Además, tienes que lidiar con la extensión de letreros. Matemáticamente, lo siguiente es lo mismo, pero se trata de extensión de signo y es independiente de la plataforma.

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

Cuando se ajusta en tiempo de ejecución, dará como resultado un rendimiento similar al de los movimientos de la broca. Esa es una de las cosas buenas de los idiomas interpretados.

+0

En realidad, necesita multiplicar por 'uint.MaxValue + 1', es decir' 0x100000000', no '0x11111111' – Sphinxxx

6

Solo por cuestión de claridad ... Mientras que la respuesta aceptada parece funcionar correctamente. Todos los trazadores de líneas presentados no parecen producir resultados precisos.

Aquí es un chiste que hace el trabajo:

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

Aquí hay un código para que pueda probar por ti mismo:

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); 
Cuestiones relacionadas