Διαδρομές
/
C#
C#
/
Ασκήσεις
/
Υπερ-βελτιστοποιημένη τηλεμετρία
Υπερ-βελτιστοποιημένη τηλεμετρία

Υπερ-βελτιστοποιημένη τηλεμετρία

Άσκηση εκμάθησης

Εισαγωγή

Ακέραιοι αριθμοί

Η C#, όπως πολλές στατικά τυπισμένες γλώσσες, παρέχει αρκετούς τύπους που αναπαριστούν ακέραιους αριθμούς, ο καθένας με το δικό του εύρος τιμών. Στο κάτω άκρο, ο τύπος sbyte έχει ελάχιστη τιμή -128 και μέγιστη τιμή 127. Όπως σε όλους τους ακέραιους τύπους, αυτές οι τιμές είναι διαθέσιμες ως <type>.MinValue και <type>.MaxValue. Στο πάνω άκρο, ο τύπος long έχει ελάχιστη τιμή -9.223.372.036.854.775.808 και μέγιστη τιμή 9.223.372.036.854.775.807. Στη μέση βρίσκονται οι τύποι short και int.

Τα εύρη καθορίζονται από το πλάτος αποθήκευσης του τύπου, όπως το δεσμεύει το σύστημα. Για παράδειγμα, ένα byte χρησιμοποιεί 8 bit και ένα long χρησιμοποιεί 64 bit.

Κάθε ένας από τους παραπάνω τύπους συνδυάζεται με έναν αντίστοιχο ανυπόγραφο τύπο: sbyte/byte, short/ushort, int/uint και long/ulong. Σε όλες τις περιπτώσεις, το εύρος των τιμών είναι από το 0 έως το αρνητικό του προσημασμένου μεγίστου επί 2 συν 1.

Type Width 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

Μια μεταβλητή (ή μια παράσταση) ενός τύπου μπορεί εύκολα να μετατραπεί σε άλλον τύπο. Για παράδειγμα, σε μια εντολή ανάθεσης, αν ο τύπος της τιμής που ανατίθεται (lhs) εξασφαλίζει ότι η τιμή θα βρίσκεται μέσα στο εύρος του τύπου στον οποίο γίνεται η ανάθεση (rhs), τότε αρκεί μια απλή ανάθεση:

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

Από την άλλη, αν το εύρος του τύπου από τον οποίο γίνεται η ανάθεση δεν είναι υποσύνολο του εύρους τιμών του δέκτη, τότε απαιτείται μια πράξη cast, (), ακόμη και αν η συγκεκριμένη τιμή βρίσκεται μέσα στο εύρος του δέκτη:

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

Μετατροπή bit

Η κλάση BitConverter παρέχει έναν βολικό τρόπο μετατροπής ακέραιων τύπων από και προς πίνακες byte.

Οδηγίες

Η εργασία συνεχίζεται στο έργο του τηλεχειριζόμενου αυτοκινήτου. Το εύρος ζώνης στο σύστημα τηλεμετρίας είναι περιορισμένο και σου έχει ζητηθεί να υλοποιήσεις ένα πρωτόκολλο μηνυμάτων για τη μετάδοση δεδομένων τηλεμετρίας.

Τα δεδομένα μεταδίδονται μέσα σε έναν buffer (πίνακας byte). Όταν αποστέλλονται ακέραιοι, το μέγεθος του buffer μειώνεται με την εφαρμογή του πρωτοκόλλου που περιγράφεται παρακάτω.

Κάθε τιμή πρέπει να αναπαρίσταται στον μικρότερο δυνατό ακέραιο τύπο (οι τύποι byte και sbyte δεν περιλαμβάνονται, καθώς η εξοικονόμηση θα ήταν αμελητέα):

Από Έως Τύπος
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

Η τιμή πρέπει να μετατρέπεται στον κατάλληλο αριθμό byte για τον τύπο που της έχει ανατεθεί. Ο πλήρης buffer περιλαμβάνει ένα byte που υποδεικνύει τον αριθμό των πρόσθετων byte στον buffer (byte προθέματος), ακολουθούμενο από τα byte που περιέχουν τον ακέραιο (byte ωφέλιμου φορτίου).

Κάποιοι από τους τύπους χρησιμοποιούν τον ίδιο αριθμό byte (π.χ. οι τύποι uint και int). Κανονικά, θα είχαν το ίδιο byte προθέματος, αλλά αυτό θα έκανε την αποκωδικοποίηση προβληματική. Για να αντιμετωπιστεί αυτό, το πρωτόκολλο εισάγει ένα μικρό τρικ: για τους προσημασμένους τύπους, η τιμή του byte προθέματος είναι 256 μείον τον αριθμό των πρόσθετων byte στον buffer.

Μόνο το byte προθέματος και ο αριθμός των επόμενων byte που υποδεικνύονται από το byte προθέματος θα αποσταλούν στην επικοινωνία. Εσωτερικά χρησιμοποιείται ένας buffer 9 byte (με μηδενικά στο τέλος, όταν χρειάζεται) τόσο από τις ρουτίνες αποστολής όσο και από τις ρουτίνες λήψης.

1. Κωδικοποίησε μια ακέραια τιμή έτοιμη για αποστολή

Υλοποίησε τη στατική μέθοδο TelemetryBuffer.ToBuffer() για να κωδικοποιήσεις έναν buffer παίρνοντας την παράμετρο που περνιέται στη μέθοδο.

// 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. Αποκωδικοποίησε έναν buffer που έλαβες

Υλοποίησε τη στατική μέθοδο TelemetryBuffer.FromBuffer() για να αποκωδικοποιήσεις τον buffer που έλαβες και να επιστρέψεις την τιμή με τη μορφή long.

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

Αν το byte προθέματος έχει μη αναμενόμενη τιμή, τότε θα πρέπει να επιστραφεί το 0.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
C# Exercism

Έτοιμος να ξεκινήσεις την άσκηση Υπερ-βελτιστοποιημένη τηλεμετρία;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις C# με 62 έννοιες178 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.