Conversion de complément à deux

J’ai besoin de convertir des octets au format complément à deux en octets positifs. La plage -128 à 127 correspond à 0 à 255.

Examples: -128 (10000000) -> 0 , 127 (01111111) -> 255, etc. 

EDIT Pour dissiper toute confusion, l’octet d’entrée est (bien sûr) un entier non signé compris entre 0 et 255. MAIS il représente un entier signé compris entre -128 et 127 en utilisant le format de complément à deux. Par exemple, la valeur d’octet d’entrée de 128 (binary 10000000) représente en réalité -128.

EXTRA EDIT Très bien, disons que nous avons le stream d’octets suivant: 0,255,254,1,127. Dans le format du complément à deux, cela représente 0, -1, -2, 1, 127. Cela nécessite une fixation de 0 à 255. Pour plus d’informations, consultez cet article difficile à trouver: Le complément de deux

De votre exemple d’entrée, vous souhaitez simplement:

 sbyte something = -128; byte foo = (byte)( something + 128); 
 new = old + 128; 

bingo 🙂

Essayer

 sbyte signed = (sbyte)input; 

ou

 int signed = input | 0xFFFFFF00; 
  public static byte MakeHexSigned(byte value) { if (value > 255 / 2) { value = -1 * (255 + 1) + value; } return value; } 
 int8_t indata; /* -128,-127,...-1,0,1,...127 */ uint8_t byte = indata ^ 0x80; 

xor MSB, c’est tout

Voici ma solution à ce problème, pour les nombres supérieurs à 8 bits. Mon exemple est pour une valeur de 16 bits. Remarque: vous devrez vérifier le premier bit pour voir s’il est négatif ou non.

Pas:

  1. Convertissez # en complément en plaçant ‘~’ avant variable. (c.-à-d. y = ~ y)

  2. Convertir #s en chaîne binary

  3. Casser des chaînes binarys dans un tableau de caractères

  4. En commençant par le plus de valeur possible, ajoutez 1, en gardant une trace des reports. Enregistrer le résultat dans un tableau de caractères.

  5. Reconvertit le tableau de caractères en chaîne.

     private ssortingng TwosComplimentMath(ssortingng value1, ssortingng value2) { char[] binary1 = value1.ToCharArray(); char[] binary2 = value2.ToCharArray(); bool carry = false; char[] calcResult = new char[16]; for (int i = 15; i >= 0; i--) { if (binary1[i] == binary2[i]) { if (binary1[i] == '1') { if (carry) { calcResult[i] = '1'; carry = true; } else { calcResult[i] = '0'; carry = true; } } else { if (carry) { calcResult[i] = '1'; carry = false; } else { calcResult[i] = '0'; carry = false; } } } else { if (carry) { calcResult[i] = '0'; carry = true; } else { calcResult[i] = '1'; carry = false; } } } ssortingng result = new ssortingng(calcResult); return result; } 

Vous pourriez décrire quelque chose d’aussi simple que d’append un biais à votre numéro (dans ce cas, en ajoutant 128 au nombre signé).

Si j’ai bien compris, votre problème est de savoir comment convertir l’entrée, qui est en réalité un signed-byte ( sbyte ), mais cette entrée est stockée dans un unsigned integer et éviter les valeurs négatives en les convertissant à zéro.

Pour être clair, lorsque vous utilisez un type signé (comme ubyte ), la structure utilise Two's complement à Two's complement derrière la scène. Il vous suffit donc de choisir le bon type pour utiliser le complément à deux.

Ensuite, une fois cette conversion effectuée, vous pouvez verrouiller les valeurs négatives avec un simple opérateur if ou ternaire conditionnel ( ?:) .

Les fonctions présentées ci-dessous renvoient 0 pour les valeurs comsockets from 128 to 255 (ou entre -128 et -1) et the same value pour les valeurs comsockets from 0 to 127 .

Donc, si vous devez utiliser des entiers non signés en entrée et en sortie, vous pouvez utiliser quelque chose comme ceci:

 private static uint ConvertSByteToByte(uint input) { sbyte properDataType = (sbyte)input; //128..255 will be taken as -128..-1 if (properDataType < 0) { return 0; } //when negative just return 0 if (input > 255) { return 0; } //just in case as uint can be greater than 255 return input; } 

Ou, à mon humble avis, vous pouvez modifier vos entrées et sorties en types de données les mieux adaptés à vos entrées et sorties (sbyte et octet):

 private static byte ConvertSByteToByte(sbyte input) { return input < 0 ? (byte)0 : (byte)input; } 

Je crois que le complément de 2 octets serait mieux fait avec ce qui suit. Peut-être pas élégant ou court mais clair et évident. Je le mettrais comme une méthode statique dans l’une de mes classes util.

 public static sbyte ConvertTo2Complement(byte b) { if(b < 128) { return Convert.ToSByte(b); } else { int x = Convert.ToInt32(b); return Convert.ToSByte(x - 256); } } 

Le problème est donc que le problème du PO n’est pas vraiment la conversion du complément à deux. Il ajoute un biais à un ensemble de valeurs afin d’ajuster la plage comprise entre -128..127 et 0..255.

Pour effectuer la conversion d’un complément à deux, vous devez simplement transtyper la valeur signée en valeur non signée, comme ceci:

 sbyte test1 = -1; byte test2 = (byte)test1; 

-1 devient 255. -128 devient 128. Cela ne sonne pas comme ce que veut le PO, cependant. Il souhaite simplement faire glisser un tableau vers le haut de sorte que la valeur signée la plus basse (-128) devienne la valeur non signée la plus basse (0).

Pour append un biais, il suffit de faire l’addition d’un nombre entier:

 newValue = signedValue+128;