2011-06-02 13 views
8

Necesito pasar un parámetro como dos parámetros int a un Informe Telerik ya que no puede aceptar parámetros largos. ¿Cuál es la forma más fácil de dividir un largo en dos partes y reconstruirlo sin perder datos?Convertir un largo a dos int para fines de reconstrucción

+3

¿Convertir a una matriz de bytes y enviar uno como los bits altos el otro como los bits bajos? Además, tu gato parece muy dulce y festejaría totalmente con mi gato. – Yuck

+1

¿Seguro que te refieres a dos entradas largas? – MGwynne

+1

¿Los números estarán firmados o sin firmar? –

Respuesta

11

Usar el enmascaramiento y el cambio es su mejor opción. long está garantizado para ser de 64 bits e int 32 bit, de acuerdo con la documentación, por lo que puede enmascarar los bits en los dos enteros y luego recombinarse.

Ver:

static int[] long2doubleInt(long a) { 
     int a1 = (int)(a & uint.MaxValue); 
     int a2 = (int)(a >> 32); 
     return new int[] { a1, a2 }; 
    } 

    static long doubleInt2long(int a1, int a2) 
    { 
     long b = a2; 
     b = b << 32; 
     b = b | (uint)a1; 
     return b; 
    } 


    static void Main(string[] args) 
    { 
     long a = 12345678910111213; 
     int[] al = long2doubleInt(a); 
     long ap = doubleInt2long(al[0],al[1]); 
     System.Console.WriteLine(ap); 
     System.Console.ReadKey(); 
    } 

Nota el uso de operaciones bit a bit en todas partes. Esto evita los problemas que uno podría tener al usar la suma u otras operaciones numéricas que podrían ocurrir usando números negativos o errores de redondeo.

Tenga en cuenta que puede reemplazar int con uint en el código anterior si puede usar enteros sin signo (esto siempre es preferible en este tipo de situación, ya que es mucho más claro lo que está sucediendo con los bits).

+1

Necesitaba marcar 'long2doubleInt' y' doubleInt2long' con 'unchecked' para admitir números negativos en el entero de la izquierda. –

1
long spork = 0x7f1234567f125953; 
int[] ints = new int[2]; 
ints[0] = (int)(spork >> 32); 
ints[1] = (int)(spork & (long)0xFFFFFFFF); 

long reconstructed = ((long)ints[0] << 32) + (long)ints[1]; 

¿Esto le sirve?

+0

Ese método no funcionará si 'spork' es un número real grande (cerca de' long.MaxValue') –

+0

No debe usar la suma aquí. Considera 'long spork = -1;'. Luego se reconstruyeron los rendimientos -4294967297. – MGwynne

2
 long x = long.MaxValue; 
     int lo = (int)(x & 0xffffffff); 
     int hi = (int)((x - ((long)lo & 0xffffffff)) >> 32); 
     long y = ((long)hi << 32) | ((long)lo & 0xffffffff); 

     Console.WriteLine(System.Convert.ToString(x, 16)); 
     Console.WriteLine(System.Convert.ToString(lo, 16)); 
     Console.WriteLine(System.Convert.ToString(hi, 16)); 
     Console.WriteLine(System.Convert.ToString(y, 16)); 
2

Para unigned el siguiente trabajo:

ulong value = ulong.MaxValue - 12; 
uint low = (uint)(value & (ulong)uint.MaxValue); 
uint high = (uint)(value >> 32); 

ulong value2 = ((ulong)high << 32) | low; 
1

de convertirlo a partir de una cadena sería mucho más simple que la conversión es dos y de un par de enteros. ¿Es esta una opción?

string myStringValue = myLongValue.ToString(); 

myLongValue = long.Parse(myStringValue); 
3

Hacer la manipulación de bits en C# puede ser incómodo a veces, especialmente cuando se trata de valores firmados. Debe usar valores sin signo siempre que planee manipular bit. Desafortunadamente no va a producir el mejor código de aspecto.

const long LOW_MASK = ((1L << 32) - 1); 
long value = unchecked((long)0xDEADBEEFFEEDDEAD); 
int valueHigh = (int)(value >> 32); 
int valueLow = (int)(value & LOW_MASK); 
long reconstructed = unchecked((long)(((ulong)valueHigh << 32) | (uint)valueLow)); 

Si quieres una manera más agradable de hacer esto, obtener los bytes primas para el largo y obtener los números enteros correspondientes de los bytes. La conversión a/desde representaciones no cambia mucho.

long value = unchecked((long)0xDEADBEEFFEEDDEAD); 
byte[] valueBytes = BitConverter.GetBytes(value); 
int valueHigh = BitConverter.ToInt32(valueBytes, BitConverter.IsLittleEndian ? 4 : 0); 
int valueLow = BitConverter.ToInt32(valueBytes, BitConverter.IsLittleEndian ? 0 : 4); 
byte[] reconstructedBytes = BitConverter.IsLittleEndian 
    ? BitConverter.GetBytes(valueLow).Concat(BitConverter.GetBytes(valueHigh)).ToArray() 
    : BitConverter.GetBytes(valueHigh).Concat(BitConverter.GetBytes(valueLow)).ToArray(); 
long reconstructed = BitConverter.ToInt64(reconstructedBytes, 0);