Track
/
C#
C#
/
Esercizi
/
Telemetria iper-ottimizzata
Telemetria iper-ottimizzata

Telemetria iper-ottimizzata

Esercizio di apprendimento

Introduzione

Numeri interi

C#, come molti linguaggi a tipizzazione statica, mette a disposizione diversi tipi che rappresentano numeri interi, ognuno con il proprio intervallo di valori. All'estremo inferiore, il tipo sbyte ha un valore minimo di -128 e un valore massimo di 127. Come per tutti i tipi interi, questi valori sono disponibili come <type>.MinValue e <type>.MaxValue. All'estremo superiore, il tipo long ha un valore minimo di -9.223.372.036.854.775.808 e un valore massimo di 9.223.372.036.854.775.807. Nel mezzo ci sono i tipi short e int.

Gli intervalli dipendono dall'ampiezza di memorizzazione che il sistema assegna al tipo. Ad esempio, un byte usa 8 bit e un long usa 64 bit.

Ognuno dei tipi precedenti è affiancato da un equivalente senza segno: sbyte/byte, short/ushort, int/uint e long/ulong. In tutti i casi l'intervallo dei valori va da 0 a due volte il massimo con segno negativo, più 1.

Tipo Ampiezza Minimo Massimo
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

Una variabile (o un'espressione) di un tipo può essere convertita facilmente in un altro tipo. Ad esempio, in un'operazione di assegnazione, se il tipo del valore che viene assegnato (lhs) garantisce che il valore rientri nell'intervallo del tipo a cui viene assegnato (rhs), allora basta una semplice assegnazione:

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

Al contrario, se l'intervallo del tipo da cui si assegna non è un sottoinsieme dell'intervallo di valori del tipo di destinazione, serve un'operazione di cast, (), anche se il valore in questione rientra nell'intervallo di destinazione:

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

Conversione di bit

La classe BitConverter offre un modo comodo per convertire i tipi interi da e verso array di byte.

Istruzioni

Il lavoro sul progetto dell'auto radiocomandata continua. La larghezza di banda nel sistema di telemetria scarseggia e ti è stato chiesto di implementare un protocollo di messaggi per comunicare i dati di telemetria.

I dati vengono trasmessi in un buffer (un array di byte). Quando si inviano numeri interi, la dimensione del buffer viene ridotta applicando il protocollo descritto di seguito.

Ogni valore dovrebbe essere rappresentato con il tipo intero più piccolo possibile (i tipi byte e sbyte non sono inclusi, perché il risparmio sarebbe trascurabile):

Da A Tipo
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

Il valore dovrebbe essere convertito nel numero di byte appropriato per il tipo assegnato. Il buffer completo comprende un byte che indica il numero di byte aggiuntivi nel buffer (byte di prefisso), seguito dai byte che contengono il numero intero (byte di payload).

Alcuni tipi usano lo stesso numero di byte (ad esempio i tipi uint e int). Normalmente avrebbero lo stesso byte di prefisso, ma questo renderebbe problematica la decodifica. Per ovviare a questo, il protocollo introduce un piccolo trucco: per i tipi con segno, il valore del loro byte di prefisso è 256 meno il numero di byte aggiuntivi nel buffer.

Nella comunicazione verranno inviati solo il byte di prefisso e il numero di byte successivi indicati dal prefisso. Internamente viene usato un buffer di 9 byte (con gli zeri finali, se necessario), sia dalle routine di invio che da quelle di ricezione.

1. Codificare un valore intero pronto per l'invio

Implementa il metodo statico TelemetryBuffer.ToBuffer() per codificare un buffer prendendo il parametro passato al metodo.

// 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. Decodificare un buffer ricevuto

Implementa il metodo statico TelemetryBuffer.FromBuffer() per decodificare il buffer ricevuto e restituire il valore sotto forma di long.

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

Se il byte di prefisso ha un valore inatteso, allora dovrebbe essere restituito 0.

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
C# Exercism

Vuoi iniziare Telemetria iper-ottimizzata?

Iscriviti a Exercism per imparare e padroneggiare C# con 62 concetti178 esercizi e il mentoring di persone reali, tutto gratis.