2017-01-11 2 views
6

J'ai un court tableau en C# et j'ai besoin de convertir deux éléments dans un Int32. Le code que j'ai écrit est le suivantConvertir un court [2] en Int32 en C#

uint pesoparz = (Convert.ToUInt16(values[0])); 
Int32 pesotot = Convert.ToInt32(pesoparz *65536 + Convert.ToUInt16(values[1])); 

où les valeurs [] est le tableau court et pesotot est le Int32 que je voudrais obtenir. Cela fonctionne mais malheureusement quand la valeur [1] dépasse 2^15, j'obtiens l'exception de débordement de système.

Pourquoi l'exception se produit-elle?

+1

utilisation 'uncheck' pour contourner. – Bauss

+0

@Bauss Droite, qui corrige superficiellement le logiciel, mais le calcul n'est toujours pas comme souhaité. – Codor

+1

L'extension de signe est probablement à l'origine de l'erreur. Essayez ceci: uint pesoparz = ((valeurs [1] & 0xFFFF) << 16) | (valeurs [0] et 0xFFFF); – jdweng

Répondre

2

Vous cherchez unchecked qui éteint IntegerOverflow:

short left = -123; 
    short right = -456; 

    int result = unchecked(BitConverter.IsLittleEndian 
    ? (UInt16)left << 16 | (UInt16)right 
    : (UInt16)right << 16 | (UInt16)left); 

Vous pouvez voulez utiliser BitConverter.IsLittleEndian pour détecter l'ordre dans lequel les pièces short doivent être combinées en int.

0

Il est préférable d'utiliser changement et ou pour cela, et utiliser unchecked pour éviter une erreur de débordement:

int result = unchecked((int)(((uint)values[0] << 16) | values[1])); 
0

essayer cette

uint pesoparz = (Convert.ToUInt16(values[0])); 
Int32 pesotot = Convert.ToInt32(pesoparz *65536 + Convert.ToUInt32(values[1])); 

semble que vous atteignez la limite

0
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); 

Cela donne un résultat correct de 33587201. L'astuce, s'il y en a une, consiste à utiliser le lancer pour obtenir les shorts en ints et ensuite masquer les parties que vous ne voulez pas (dans ce cas, l'extension de signe). Cela ne nécessite ni Convert ni unchecked.

2

Vous pouvez utiliser des opérateurs au niveau du bit:

short[] parts = new short[2]; 
parts[0] = 1; 
parts[1] = 2; 

uint result = 0; 

result = (ushort)parts[0] << 16 | (ushort)parts[1]; 

Le résultat sera 0x00010002 en hexadécimal ou 65538 en décimal.

0

Etes-vous sûr que chaque valeur de votre tableau de valeurs s'inscrit dans un Int16?

Sinon, même si vous décochez la case, le résultat n'est pas ce que vous voulez. D'abord vous devrez décider quoi faire si les valeurs [0] ou les valeurs 1 sont plus grandes que les ajustements dans un Int16.

Votre décision dépend de ce que signifient les valeurs. Est-ce que les valeurs [0] représentent les 16 bits les plus élevés de votre Int32 et les valeurs [0] les 16 bits les plus bas?

Dans ce cas, vous devriez lancer une ArgumentException si les valeurs [0] ou les valeurs 1 sont supérieures à Int16.MaxValue. Après que votre code est facile:

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; 

Cela pourrait également signifier qu'il est admis que les deux valeurs sont plus que 0x10000, vous devriez penser à vous-même ce que vous voulez en conséquence si les chiffres sont trop gros. Par ailleurs, si vos valeurs représentent chacune la moitié d'un Int32, pensez à changer la signification des valeurs [0] et des valeurs 1. Presque toujours les bits les moins significatifs (LSB) sont dans [0], tandis que les bits les plus significatifs (MSB) sont dans 1.Si vous suivez cette convention, vous n'avez pas à écrire ces convertisseurs vous-même, vous pouvez utiliser le BitConverter class

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