Parcours
/
C#
C#
/
Exercices
/
Télémétrie hyper-optimisée
Télémétrie hyper-optimisée

Télémétrie hyper-optimisée

Exercice d'apprentissage

Introduction

Nombres entiers

C#, comme beaucoup de langages à typage statique, fournit un certain nombre de types qui représentent des entiers, chacun avec sa propre plage de valeurs. À l'extrémité basse, le type sbyte a une valeur minimale de -128 et une valeur maximale de 127. Comme pour tous les types entiers, ces valeurs sont disponibles sous la forme <type>.MinValue et <type>.MaxValue. À l'extrémité haute, le type long a une valeur minimale de -9 223 372 036 854 775 808 et une valeur maximale de 9 223 372 036 854 775 807. Entre les deux se trouvent les types short et int.

Les plages sont déterminées par la largeur de stockage du type, telle qu'allouée par le système. Par exemple, un byte utilise 8 bits et un long utilise 64 bits.

Chacun des types ci-dessus est associé à un équivalent non signé : sbyte/byte, short/ushort, int/uint et long/ulong. Dans tous les cas, la plage de valeurs va de 0 au maximum signé négatif multiplié par 2, plus 1.

Type Largeur Minimum Maximum
sbyte 8 bit -128 +127
short 16 bit -32_768 +32_767
int 32 bit -2_147_483_648 +2_147_483_647
long 64 bit -9_223_372_036_854_775_808 +9_223_372_036_854_775_807
byte 8 bit 0 +255
ushort 16 bit 0 +65_535
uint 32 bit 0 +4_294_967_295
ulong 64 bit 0 +18_446_744_073_709_551_615

Une variable (ou une expression) d'un type peut facilement être convertie en un autre. Par exemple, dans une affectation, si le type de la valeur affectée (lhs) garantit que cette valeur se situera dans la plage du type de destination (rhs), alors une simple affectation suffit :

uint ui = uint.MaxValue;
ulong ul = ui;    // no problem

En revanche, si la plage du type source n'est pas un sous-ensemble de la plage de valeurs du type de destination, une opération de cast, (), est nécessaire, même si la valeur particulière se trouve dans la plage du type de destination :

short s = 42;
uint ui = (uint)s;

Conversion en bits

La classe BitConverter offre un moyen pratique de convertir des types entiers vers des tableaux d'octets et inversement.

Instructions

Le travail se poursuit sur le projet de voiture télécommandée. La bande passante du système de télémétrie est limitée et on t'a demandé d'implémenter un protocole de messages pour transmettre les données de télémétrie.

Les données sont transmises dans un tampon (un tableau d'octets). Lorsque des entiers sont envoyés, la taille du tampon est réduite grâce au protocole décrit ci-dessous.

Chaque valeur doit être représentée dans le plus petit type entier possible (les types byte et sbyte ne sont pas inclus, car le gain serait négligeable) :

De À Type
4_294_967_296 9_223_372_036_854_775_807 long
2_147_483_648 4_294_967_295 uint
65_536 2_147_483_647 int
0 65_535 ushort
-32_768 -1 short
-2_147_483_648 -32_769 int
-9_223_372_036_854_775_808 -2_147_483_649 long

La valeur doit être convertie dans le nombre d'octets approprié à son type. Le tampon complet comprend un octet indiquant le nombre d'octets supplémentaires qu'il contient (octet de préfixe), suivi des octets qui portent l'entier (octets de charge utile).

Certains types utilisent un nombre identique d'octets (par exemple les types uint et int). Normalement, ils auraient le même octet de préfixe, mais cela rendrait le décodage problématique. Pour y remédier, le protocole introduit une petite astuce : pour les types signés, la valeur de leur octet de préfixe est 256 moins le nombre d'octets supplémentaires dans le tampon.

Seuls l'octet de préfixe et le nombre d'octets suivants indiqués par celui-ci sont envoyés lors de la communication. En interne, un tampon de 9 octets est utilisé (avec des zéros de remplissage si nécessaire), aussi bien par les routines d'envoi que de réception.

1. Encode une valeur entière prête à l'envoi

Implémente la méthode statique TelemetryBuffer.ToBuffer() pour encoder un tampon à partir du paramètre passé à la méthode.

// Type: ushort, bytes: 2, signed: no, prefix byte: 2
TelemetryBuffer.ToBuffer(5)
// => {0x2, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

// Type: int, bytes: 4, signed: yes, prefix byte: 256 - 4
TelemetryBuffer.ToBuffer(Int32.MaxValue)
// => {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 };

2. Décode un tampon reçu

Implémente la méthode statique TelemetryBuffer.FromBuffer() pour décoder le tampon reçu et renvoyer la valeur sous la forme d'un long.

TelemetryBuffer.FromBuffer(new byte[] {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 })
// => 2147483647

Si la valeur de l'octet de préfixe est inattendue, il faut renvoyer 0.

Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
C# Exercism

Prêt à commencer Télémétrie hyper-optimisée ?

Inscris-toi sur Exercism pour apprendre et maîtriser C# avec 62 concepts178 exercices, et un vrai mentorat humain, le tout gratuitement.