Tracks
/
C#
C#
/
Übungen
/
Hyperoptimierte Telemetrie
Hyperoptimierte Telemetrie

Hyperoptimierte Telemetrie

Lernübung

Einführung

Ganzzahlen

C# bietet wie viele statisch typisierte Sprachen eine Reihe von Typen, die Ganzzahlen darstellen, jeder mit seinem eigenen Wertebereich. Am unteren Ende hat der Typ sbyte einen Minimalwert von -128 und einen Maximalwert von 127. Wie bei allen Ganzzahltypen stehen diese Werte als <type>.MinValue und <type>.MaxValue zur Verfügung. Am oberen Ende hat der Typ long einen Minimalwert von -9.223.372.036.854.775.808 und einen Maximalwert von 9.223.372.036.854.775.807. Dazwischen liegen die Typen short und int.

Die Wertebereiche ergeben sich aus der Speicherbreite, die das System dem Typ zuweist. Ein byte belegt zum Beispiel 8 Bits und ein long 64 Bits.

Zu jedem der obigen Typen gibt es ein vorzeichenloses Gegenstück: sbyte/byte, short/ushort, int/uint und long/ulong. In allen Fällen reicht der Wertebereich von 0 bis zum Zweifachen des negativen Maximums des vorzeichenbehafteten Typs plus 1.

Typ Breite 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

Eine Variable (oder ein Ausdruck) eines Typs lässt sich leicht in einen anderen umwandeln. Bei einer Zuweisung genügt zum Beispiel eine einfache Zuweisung, wenn der Typ des Wertes, der zugewiesen wird (lhs), sicherstellt, dass der Wert im Wertebereich des Typs liegt, dem zugewiesen wird (rhs):

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

Andererseits ist ein Cast nötig, also eine ()-Operation, wenn der Wertebereich des Ausgangstyps keine Teilmenge des Wertebereichs des Zieltyps ist, selbst wenn der konkrete Wert im Wertebereich des Zieltyps liegt:

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

Bitkonvertierung

Die Klasse BitConverter bietet eine bequeme Möglichkeit, Ganzzahltypen in Byte-Arrays und zurück umzuwandeln.

Anleitung

Die Arbeit am ferngesteuerten Auto geht weiter. Die Bandbreite im Telemetriesystem ist äußerst knapp, und du wurdest gebeten, ein Nachrichtenprotokoll für die Übertragung von Telemetriedaten zu implementieren.

Die Daten werden in einem Puffer (Byte-Array) übertragen. Beim Senden von Ganzzahlen wird die Größe des Puffers reduziert, indem das unten beschriebene Protokoll verwendet wird.

Jeder Wert sollte im kleinstmöglichen Ganzzahltyp dargestellt werden (die Typen byte und sbyte sind nicht enthalten, da die Einsparung vernachlässigbar wäre):

Von Bis Typ
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

Der Wert sollte in die passende Anzahl von Bytes für seinen zugewiesenen Typ umgewandelt werden. Der vollständige Puffer besteht aus einem Byte, das die Anzahl der zusätzlichen Bytes im Puffer angibt (Präfixbyte), gefolgt von den Bytes, die die Ganzzahl enthalten (Nutzbytes).

Einige der Typen verwenden eine identische Anzahl von Bytes (z. B. die Typen uint und int). Normalerweise hätten sie dasselbe Präfixbyte, aber das würde die Dekodierung problematisch machen. Um dem entgegenzuwirken, führt das Protokoll einen kleinen Trick ein: Bei vorzeichenbehafteten Typen ist der Wert ihres Präfixbytes 256 minus der Anzahl der zusätzlichen Bytes im Puffer.

In der Kommunikation werden nur das Präfixbyte und die Anzahl der darauffolgenden Bytes gesendet, die das Präfix angibt. Intern wird sowohl beim Senden als auch beim Empfangen ein 9 Byte großer Puffer verwendet (mit abschließenden Nullen, falls nötig).

1. Einen Ganzzahlwert zum Senden kodieren

Bitte implementiere die statische Methode TelemetryBuffer.ToBuffer(), die einen Puffer kodiert und dabei den an die Methode übergebenen Parameter verwendet.

// 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. Einen empfangenen Puffer dekodieren

Bitte implementiere die statische Methode TelemetryBuffer.FromBuffer(), um den empfangenen Puffer zu dekodieren und den Wert in Form eines long zurückzugeben.

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

Wenn das Präfixbyte einen unerwarteten Wert hat, sollte 0 zurückgegeben werden.

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
C# Exercism

Bereit, mit Hyperoptimierte Telemetrie zu starten?

Melde dich bei Exercism an, um C# mit 62 Konzepte178 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.