c# - implicito - casting programming
Convierte un Corto[2] a Int32 en C# (6)
Tengo una matriz corta en c # y necesito convertir dos elementos en un Int32. El código que escribí es el siguiente
uint pesoparz = (Convert.ToUInt16(values[0]));
Int32 pesotot = Convert.ToInt32(pesoparz *65536 + Convert.ToUInt16(values[1]));
donde valores [] es la matriz corta y pesotot es la Int32 que me gustaría obtener. Funciona pero desafortunadamente cuando el valor [1] excede 2 ^ 15, obtengo la excepción de desbordamiento del sistema.
¿Por qué ocurre la excepción?
¿Estás seguro de que cada valor de tu matriz de valores se ajusta a un Int16?
De lo contrario, incluso si desmarcas, el resultado no es el que deseas. Primero, tendrá que decidir qué hacer si los valores [0] o los valores 1 son mayores que los que caben en un Int16.
Tu decisión depende de lo que signifiquen los valores. ¿Los valores [0] representan los 16 bits más altos de su Int32 resultante y los valores [0] los 16 bits más bajos?
En ese caso, debe lanzar una ArgumentException si los valores [0] o los valores 1 son más que Int16.MaxValue. Después de eso, tu código es fácil:
if (values[0] > Int16.MaxValue || values[1] > Int16.MaxValue)
throw new ArgumentException("values should fit in two bytes");
Int32 result = values[0] << 0x10000 + values[1];
return result;
También podría significar que está permitido que ambos valores sean más de 0x10000. Debería pensar en sí mismo lo que quiere como resultado si los números son demasiado grandes.
Por cierto, si sus valores representan cada uno la mitad de un Int32, considere cambiar el significado de los valores [0] y los valores 1 . Casi siempre los bits menos significativos (LSB) están en [0], mientras que los bits más significativos (MSB) están en 1 . Si sigues esta convención, no tienes que escribir estos convertidores tú mismo, puedes usar la clase BitConverter
Int32 original = 0x12345678;
byte[] bytes = BitConverter.GetBytes(original);
foreach (var b in bytes)
Console.WriteLine(b.ToString("02X"); // write in two digit hex format
// will write lines with 78 56 34 12
Int16[] Values = new Int16[]
{
BitConverter.ToInt16(bytes), // LSB
BitConverter.ToInt16(bytes, 2), // MSB
};
Int32 result = (Int32)values[0] + (Int32)values[1] << 0x10000;
Debug.Assert(original == result);
Está buscando unchecked
IntegerOverflow
que apaga IntegerOverflow
:
short left = -123;
short right = -456;
int result = unchecked(BitConverter.IsLittleEndian
? (UInt16)left << 16 | (UInt16)right
: (UInt16)right << 16 | (UInt16)left);
Es posible que desee utilizar BitConverter.IsLittleEndian
para detectar el orden en que short
partes short
deben combinar en int
.
Lo mejor es usar shift y o para esto, y usar unchecked
para evitar un error de desbordamiento:
int result = unchecked((int)(((uint)values[0] << 16) | values[1]));
Puedes usar operadores bit a bit:
short[] parts = new short[2];
parts[0] = 1;
parts[1] = 2;
uint result = 0;
result = (ushort)parts[0] << 16 | (ushort)parts[1];
El resultado será 0x00010002
en hexadecimal o 65538
en decimal.
prueba esto
uint pesoparz = (Convert.ToUInt16(values[0]));
Int32 pesotot = Convert.ToInt32(pesoparz *65536 + Convert.ToUInt32(values[1]));
Parece que estás llegando al límite
short[] arr = new short[] { 512, -32767 };
int ival = ((int)arr[0] * 65536) + ((int)arr[1] & 0xffff);
// also:
// ival = ((int)arr[0] << 16) | ((int)arr[1] & 0xffff);
Console.WriteLine(ival);
Esto da un resultado correcto de 33587201
. El truco, si es que hay uno, es usar casting para poner los cortos en ints y luego enmascarar las partes que no quieres (en este caso, la extensión del signo). Esto no requiere Convert
ni unchecked
.