Αναπαράσταση δεδομένων
Δυαδικό και δεκαεξαδικό, αρνητικοί αριθμοί, χαρακτήρες και Unicode.
45 λεπτά
Θα μάθεις να
- Να μετατρέπεις αριθμούς ανάμεσα στο δεκαδικό, το δυαδικό και το δεκαεξαδικό σύστημα.
- Να γράφεις αρνητικούς ακέραιους σε 8 bit με συμπλήρωμα ως προς 2 και να ξέρεις το εύρος τους.
- Να εξηγείς πώς κωδικοποιούνται οι χαρακτήρες στο ASCII και στο Unicode.
- Να υπολογίζεις πόσα bytes πιάνει ένα κείμενο στο UTF-8, με ελληνικά και λατινικά γράμματα.
Bit και byte
Ο υπολογιστής αποθηκεύει τα πάντα ως σειρές από bit (binary digit), δηλαδή ψηφία που παίρνουν μόνο δύο τιμές, και . Οκτώ bit κάνουν ένα byte. Με bit φτιάχνονται διαφορετικοί συνδυασμοί: ένα byte έχει .
Τρία συστήματα αρίθμησης
Όλα είναι θεσιακά: η αξία ενός ψηφίου εξαρτάται από τη θέση του. Στο δεκαδικό κάθε θέση αξίζει δέκα φορές την προηγούμενη, στο δυαδικό δύο, στο δεκαεξαδικό δεκαέξι. Το δεκαεξαδικό χρειάζεται δεκαέξι ψηφία, οπότε μετά το χρησιμοποιεί τα γράμματα A έως F για τις τιμές έως .
| Δεκαδικό | Δυαδικό | Δεκαεξαδικό |
|---|---|---|
0000 | 0 | |
0101 | 5 | |
1001 | 9 | |
1010 | A | |
1101 | D | |
1111 | F |
Από δυαδικό σε δεκαδικό: πρόσθεσε τις δυνάμεις του που αντιστοιχούν στους άσσους.
Από δεκαδικό σε δυαδικό: διαίρεσε διαδοχικά με το και κράτα τα υπόλοιπα. Το αποτέλεσμα διαβάζεται από κάτω προς τα πάνω.
| Διαίρεση | Πηλίκο | Υπόλοιπο |
|---|---|---|
Από κάτω προς τα πάνω: 101101.
Ανάμεσα σε δυαδικό και δεκαεξαδικό η μετατροπή είναι σχεδόν δωρεάν, γιατί : κάθε δεκαεξαδικό ψηφίο αντιστοιχεί σε ακριβώς τέσσερα bit. Χωρίζεις σε τετράδες από τα δεξιά: 0010 1101 γίνεται 2D. Γι' αυτό το δεκαεξαδικό χρησιμοποιείται παντού στην πληροφορική: ένα byte γράφεται με δύο ψηφία αντί για οκτώ. Τα χρώματα στις ιστοσελίδες, όπως #FF8800, είναι τρία bytes σε δεκαεξαδικό: κόκκινο , πράσινο , μπλε .
Αρνητικοί αριθμοί: συμπλήρωμα ως προς 2
Η πρώτη ιδέα είναι να αφιερώσεις ένα bit στο πρόσημο. Έχει όμως δύο προβλήματα: υπάρχουν δύο μηδενικά, το και το , και η πρόσθεση θέλει ειδικούς κανόνες για τα πρόσημα. Οι υπολογιστές χρησιμοποιούν αντί γι' αυτό το συμπλήρωμα ως προς 2 (two's complement).
Για να γράψεις το σε bit:
- Γράψε το σε bit.
- Αντέστρεψε κάθε bit: τα γίνονται και τα γίνονται .
- Πρόσθεσε .
| Βήμα | Για το |
|---|---|
| το σε bit | 00101101 |
| αντιστροφή | 11010010 |
| συν | 11010011 |
Το αριστερότερο bit λειτουργεί ως bit προσήμου: για μη αρνητικούς, για αρνητικούς. Το μεγάλο πλεονέκτημα φαίνεται στην πρόσθεση:
00101101 (+45)
+ 11010011 (-45)
----------
1 00000000 το ένατο bit δεν χωράει στα 8 και απορρίπτεται
Το αποτέλεσμα είναι , με την ίδια πρόσθεση που κάνει η ΑΛΜ για τους θετικούς. Ένα κύκλωμα αρκεί και για τα δύο.
Χαρακτήρες: ASCII και Unicode
Για να γραφτεί κείμενο, κάθε χαρακτήρας αντιστοιχίζεται σε έναν αριθμό. Ο πρώτος διαδεδομένος πίνακας ήταν το ASCII (1963): bit, χαρακτήρες, με τα λατινικά γράμματα, τα ψηφία, τα σημεία στίξης και μερικούς χαρακτήρες ελέγχου.
| Χαρακτήρας | Κωδικός ASCII | Δυαδικό | Δεκαεξαδικό |
|---|---|---|---|
0 | 00110000 | 30 | |
A | 01000001 | 41 | |
a | 01100001 | 61 |
Τα κεφαλαία και τα πεζά απέχουν ακριβώς , δηλαδή ένα μόνο bit. Τα ελληνικά δεν χωρούσαν στο ASCII, και για χρόνια χρησιμοποιούνταν πίνακες bit ειδικά για τα ελληνικά. Ένα αρχείο γραμμένο με έναν πίνακα και διαβασμένο με άλλον έβγαζε ακατάληπτα σύμβολα.
Η λύση ήρθε με το Unicode: ένας ενιαίος κατάλογος που δίνει σε κάθε χαρακτήρα κάθε γραφής έναν αριθμό, το σημείο κώδικα (code point). Το «A» είναι U+0041, το «Γ» είναι U+0393, το «α» είναι U+03B1. Ο κατάλογος έχει χώρο για πάνω από ένα εκατομμύριο χαρακτήρες.
Το Unicode λέει ποιος αριθμός. Το UTF-8 λέει πώς γράφεται σε bytes, και χρησιμοποιεί μεταβλητό μήκος:
| Χαρακτήρες | Bytes στο UTF-8 | Παράδειγμα |
|---|---|---|
| οι του ASCII | «A» → 41 | |
| ελληνικά, κυριλλικά, αραβικά και άλλα | «Γ» → CE 93 | |
| τα περισσότερα υπόλοιπα, π.χ. κινεζικά, το σύμβολο του ευρώ | «€» → E2 82 AC | |
| emoji και σπάνιοι χαρακτήρες | 😀 → F0 9F 98 80 |
Το έξυπνο στο UTF-8 είναι ότι ένα κείμενο γραμμένο μόνο σε ASCII είναι ήδη έγκυρο UTF-8, byte προς byte. Γι' αυτό επικράτησε: σήμερα η συντριπτική πλειονότητα των ιστοσελίδων είναι σε UTF-8.
for s in ["A", "Γ", "€", "Γεια", "Hi"]:
print(s, len(s), len(s.encode("utf-8")))
print(ord("A"), chr(97), hex(ord("Γ")))
print(bin(45), hex(45), int("101101", 2))
print(format(-45 & 0xFF, "08b")) # το -45 σε 8 bit, συμπλήρωμα ως προς 2
Η πρώτη επανάληψη τυπώνει για το «Γεια» 4 χαρακτήρες και 8 bytes, για το «Hi» 2 και 2. Οι τρεις τελευταίες γραμμές τυπώνουν 65 a 0x393, 0b101101 0x2d 45 και 11010011.
Λυμένα παραδείγματα
Παράδειγμα 1
Γράψε το στο δυαδικό και στο δεκαεξαδικό.
Δοκίμασέ το πρώτα. Μετά δες τη λύση.
Παράδειγμα 2
Γράψε το σε bit με συμπλήρωμα ως προς 2 και έλεγξε το αποτέλεσμα.
Δοκίμασέ το πρώτα. Μετά δες τη λύση.
Παράδειγμα 3
Πόσα bytes πιάνει στο UTF-8 το κείμενο «Καλημέρα!»;
Δοκίμασέ το πρώτα. Μετά δες τη λύση.
Ασκήσεις
Πρώτα ερωτήσεις με επιλογές: διαλέγεις, πατάς «Έλεγξε» και μαθαίνεις αμέσως αν το βρήκες και γιατί. Στο τέλος, λίγες ασκήσεις χωρίς επιλογές — εκεί κρύβεται μόνο η απάντηση.
Τα κατάφερες;
- Να μετατρέπεις αριθμούς ανάμεσα στο δεκαδικό, το δυαδικό και το δεκαεξαδικό σύστημα.
- Να γράφεις αρνητικούς ακέραιους σε 8 bit με συμπλήρωμα ως προς 2 και να ξέρεις το εύρος τους.
- Να εξηγείς πώς κωδικοποιούνται οι χαρακτήρες στο ASCII και στο Unicode.
- Να υπολογίζεις πόσα bytes πιάνει ένα κείμενο στο UTF-8, με ελληνικά και λατινικά γράμματα.
Λύσε τις ασκήσεις πιο πάνω και θα δεις εδώ πού στέκεσαι.