Περίληψη
Οι αριθμοί με δεκαδικά ενός προγράμματος δεν είναι οι πραγματικοί αριθμοί των μαθηματικών: είναι ένα πεπερασμένο υποσύνολο ρητών με παρονομαστή δύναμη του δύο, και κάθε τιμή που δεν ανήκει σε αυτό το υποσύνολο αντικαθίσταται από την πλησιέστερη που ανήκει. Το μάθημα αυτό μελετά πώς αποθηκεύεται ένας αριθμός κινητής υποδιαστολής σε 64 bit (πρόσημο, εκθέτης και mantissa), γιατί το δεν έχει ακριβή αναπαράσταση και ποια τιμή παίρνει τη θέση του, πόσα ψηφία είναι ασφαλή στον float και στον double, πώς συσσωρεύονται τα σφάλματα στρογγυλοποίησης, γιατί δύο πραγματικοί δεν συγκρίνονται με == και πώς συγκρίνονται με μια αιτιολογημένη ανοχή, και τι είναι το άπειρο και ο μη αριθμός, που η μορφή δεσμεύει για τα αποτελέσματα που δεν χωρούν ή δεν υπάρχουν.
Μαθησιακοί στόχοι
- Να εξηγείτε γιατί το δεν έχει ακριβή δυαδική αναπαράσταση και ποια τιμή αποθηκεύεται στη θέση του.
- Να προβλέπετε την επίδραση της στρογγυλοποίησης σε επαναλαμβανόμενες προσθέσεις και στην πρόσθεση αριθμών πολύ διαφορετικών μεγεθών.
- Να συγκρίνετε πραγματικούς αριθμούς με κατάλληλη ανοχή αντί για
==, αιτιολογώντας την επιλογή της ανοχής. - Να επιλέγετε ανάμεσα σε
floatκαιdoubleανάλογα με την απαιτούμενη ακρίβεια, και να αναγνωρίζετε το άπειρο και τον μη αριθμό.
Επιστημονική γραφή στη βάση 2
Το μάθημα Οι ακέραιοι και η αναπαράστασή τους έδειξε ότι ένας ακέραιος bit αναπαριστά ακριβώς διαδοχικές τιμές. Ωστόσο, οι αριθμοί με δεκαδικά θέτουν μια διαφορετική δυσκολία: ανάμεσα σε δύο οποιουσδήποτε πραγματικούς υπάρχουν άπειροι άλλοι, και κανένα πεπερασμένο πλήθος bit δεν μπορεί να τους διακρίνει όλους. Η λύση που υιοθετούν όλοι οι σημερινοί υπολογιστές είναι η ίδια που χρησιμοποιεί η επιστήμη για να γράφει πολύ μεγάλα ή πολύ μικρά μεγέθη: η επιστημονική γραφή. Στη βάση 10, η μέση απόσταση της Γης από τον Ήλιο γράφεται μέτρα· ο αριθμός έχει ένα πρόσημο, λίγα σημαντικά ψηφία (τη mantissa, ) και μια δύναμη της βάσης (τον εκθέτη, ), που λέει πού μπαίνει η υποδιαστολή. Αν αυτό ισχύει, με σταθερό πλήθος ψηφίων καλύπτονται μεγέθη πολύ διαφορετικών τάξεων, με τίμημα να φυλάσσονται μόνο τα πρώτα ψηφία του καθενός.
Ο υπολογιστής κάνει το ίδιο στη βάση 2. Κάθε αριθμός διάφορος του μηδενός γράφεται με μοναδικό τρόπο ως
όπου είναι το πρόσημο (0 για θετικό, 1 για αρνητικό), είναι η mantissa γραμμένη στο δυαδικό, της οποίας το πρώτο ψηφίο είναι πάντα 1, και είναι ο εκθέτης. Το ότι το πρώτο ψηφίο είναι πάντα 1 έχει μια πρακτική συνέπεια: δεν χρειάζεται να αποθηκευτεί, και το bit που εξοικονομείται κερδίζεται για την ακρίβεια. Το όνομα κινητή υποδιαστολή περιγράφει ακριβώς αυτή τη μορφή: η υποδιαστολή δεν έχει σταθερή θέση ανάμεσα στα ψηφία, αλλά «μετακινείται» ανάλογα με τον εκθέτη.
Ο τύπος double της C++ χρησιμοποιεί σε όλους τους σημερινούς μεταγλωττιστές τη διεθνώς τυποποιημένη δυαδική μορφή διπλής ακρίβειας, των 64 bit: 1 bit για το πρόσημο, 11 bit για τον εκθέτη και 52 bit για τη mantissa, χωρίς το αρχικό ψηφίο. Ο εκθέτης αποθηκεύεται μετατοπισμένος: το πεδίο των 11 bit περιέχει , ώστε φυλάσσει μη προσημασμένες τιμές από 1 έως 2046 για εκθέτες από έως (οι τιμές 0 και 2047 του πεδίου δεσμεύονται για το μηδέν, τους πολύ μικρούς αριθμούς, το άπειρο και τον μη αριθμό, που θα δούμε στο τέλος του μαθήματος). Ο τύπος float χρησιμοποιεί τη μορφή απλής ακρίβειας, των 32 bit: 1 για το πρόσημο, 8 για τον εκθέτη και 23 για τη mantissa.
Τα bit ενός double μπορούν να φανούν. Το πρόγραμμα που ακολουθεί χρησιμοποιεί τη std::bit_cast, από την κεφαλίδα <bit>, που ερμηνεύει ξανά τα 64 bit του αριθμού ως μη προσημασμένο ακέραιο 64 bit, χωρίς να αλλάξει κανένα· εδώ χρησιμοποιείται χωρίς περαιτέρω εξήγηση, ως όργανο για να κοιτάξουμε τη μνήμη. Η προδιαγραφή μορφής {:064b} γράφει αυτόν τον ακέραιο στο δυαδικό με 64 ψηφία, όπως στο μάθημα που προηγήθηκε, και η {:016X} στο δεκαεξαδικό με 16.
#include <bit>#include <cstdint>#include <print>int main(){ const double tenth{0.1}; // Τα 64 bit του αριθμού, διαβασμένα ως μη προσημασμένος ακέραιος. const std::uint64_t bits{std::bit_cast<std::uint64_t>(tenth)}; std::println("{:064b}", bits); std::println("{:016X}", bits);}00111111101110011001100110011001100110011001100110011001100110103FB999999999999AΤο σχήμα ομαδοποιεί τα 64 bit που έγραψε το πρόγραμμα και τα διαβάζει πεδίο προς πεδίο.
Απόδειξη
Τα 64 bit, στο δεκαεξαδικό
3FB999999999999A. Διαβάζονται από αριστερά προς τα δεξιά: 1 bit για το πρόσημο, 11 για τον εκθέτη και 52 για τη mantissa.Το πρόσημο είναι 0: ο αριθμός είναι θετικός.
Το πεδίο του εκθέτη, στο δυαδικό, ισούται με 1019· αφαιρείται η μετατόπιση, 1023, και ο εκθέτης είναι .
Η mantissa, με το αρχικό 1 που δεν αποθηκεύεται, είναι στο δυαδικό: η ομάδα επαναλαμβάνεται και η τελευταία ομάδα, , είναι στρογγυλοποιημένη προς τα πάνω. Η τιμή της είναι περίπου .
Ο αριθμός που αποθηκεύτηκε είναι , δηλαδή : πολύ κοντά στο , αλλά όχι .
Φόρτωση του περιεχομένου…
Ολοκληρώθηκε
Συνδεθείτε για να αποθηκεύσετε την πρόοδό σας