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;
Die Klasse BitConverter bietet eine bequeme Möglichkeit, Ganzzahltypen in Byte-Arrays und zurück umzuwandeln.
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).
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 };
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.
Melde dich bei Exercism an, um C# mit 62 Konzepte178 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.