0

IEEE-754 Float Visualizer

Δείτε πώς ακριβώς αποθηκεύεται ένας δεκαδικός αριθμός ως float IEEE-754 — bit πρόσημου, bit εκθέτη και bit mantissa — και γιατί αριθμοί όπως το 0,1 δεν αποθηκεύονται ακριβώς.

Buy Me a Coffee at ko-fi.com
Επεξεργασία... 0%
Κανονικοποίηση
Υπολογισμός μεροληψίας εκθέτη
Επέκταση των κομματιών mantissa
Έγινε

Αποτέλεσμα

Κάθε αριθμός κινητής υποδιαστολής που αποθηκεύει ένας υπολογιστής - ένας αριθμός JavaScript, ένας float C, ένας float Python - κωδικοποιείται με τον ίδιο τρόπο στο IEEE 754: ένα bit πρόσημου, ένα μπλοκ bit εκθέτη και ένα μπλοκ bit mantissa (κλάσμα). Η απλή ακρίβεια (32-bit) χρησιμοποιεί 1 bit πρόσημου, 8 bit εκθέτη και 23 bit mantissa. διπλής ακρίβειας (64-bit), η μορφή πίσω από τον προεπιλεγμένο τύπο αριθμού σχεδόν κάθε γλώσσας, χρησιμοποιεί 1 bit πρόσημου, 11 bit εκθέτη και 52 bit mantissa. Αυτό το εργαλείο παίρνει οποιονδήποτε δεκαδικό αριθμό που πληκτρολογείτε, τον κωδικοποιεί σε οποιοδήποτε πλάτος χρησιμοποιώντας τον float encoder DataView/ArrayBuffer του προγράμματος περιήγησης — τον ίδιο μηχανισμό στον οποίο εκτελείται στην πραγματικότητα ο κώδικάς σας — και χρωματίζει κάθε bit ανάλογα με την περιοχή στην οποία ανήκει.

Η ίδια η κωδικοποίηση ακολουθεί τρία βήματα, και αυτό το εργαλείο διαπερνά όλα αυτά αντί να δείχνει απλώς τα τελικά bits. Πρώτον, κανονικοποίηση: ο αριθμός ξαναγράφεται ως 1.mantissa × 2^εκθέτης, με ακριβώς ένα μη μηδενικό ψηφίο πριν από το δυαδικό σημείο (οι αριθμοί πολύ μικροί για αυτό λαμβάνουν την υποκανονική επεξεργασία, χωρίς σιωπηρό 1). Δεύτερον, μεροληψία εκθέτη: δεδομένου ότι το πεδίο του εκθέτη πρέπει να αποθηκεύει τόσο θετικούς όσο και αρνητικούς εκθέτες ως ασήμαντο αριθμό, προστίθεται μια σταθερή πόλωση (127 για απλή ακρίβεια, 1023 για διπλή) πριν το πεδίο γραφτεί σε δυαδικό. Τρίτον, η κλασματική μάντισσα επεκτείνεται σπιθαμή προς σπιθαμή με την κλασική μέθοδο "πολλαπλασιάστε επί δύο, πάρτε το ακέραιο μέρος ως επόμενο bit, κρατήστε το υπόλοιπο" — επαναλαμβάνεται μέχρι να γεμίσει το πεδίο mantissa, οπότε τα εναπομείναντα bits αποφασίζουν εάν το αποτέλεσμα στρογγυλοποιείται προς τα πάνω ή προς τα κάτω (στρογγυλοποίηση από μισό έως ζυγό, προεπιλογή IEEE-75).

Αυτός είναι ακριβώς ο λόγος που ένας αριθμός τόσο συνηθισμένος όσο το 0,1 δεν αποθηκεύεται ακριβώς. Στο δυαδικό, το 0,1 είναι ένα επαναλαμβανόμενο κλάσμα (0,0001100110011…, για πάντα), επομένως καμία πεπερασμένη μάντισσα δεν μπορεί να το κρατήσει με ακρίβεια — πρέπει να στρογγυλοποιηθεί κάπου. Κωδικοποιήστε το 0,1 ως float 32 bit και διαβάστε τα bit πίσω, και δεν λαμβάνετε 0,1 πίσω: παίρνετε ακριβώς 0,100000001490116119384765625. Η διπλή ακρίβεια έχει 29 περισσότερα bit mantissa για να δουλέψει, επομένως το σφάλμα στρογγυλοποίησης είναι πολύ μικρότερο, αλλά δεν είναι ούτε μηδέν — το 0,1 ως διπλό 64 bit είναι ακριβώς 0,10000000000000000055551115123125782702115452583. Αυτό το εργαλείο υπολογίζει αυτήν την ακριβή αποθηκευμένη τιμή με αριθμητική μεγάλου ακέραιου αριθμού (χωρίς συντομεύσεις κινητής υποδιαστολής), έτσι ώστε το χάσμα μεταξύ αυτού που πληκτρολογήσατε και αυτού που πραγματικά διατηρεί το υλικό να μην είναι ποτέ κρυφό ή κατά προσέγγιση.

Οι ειδικές τιμές παίρνουν ακριβή, δεσμευμένα μοτίβα bit αντί για μια κανονική κωδικοποίηση: το μηδέν και το αρνητικό μηδέν έχουν bit εκθέτη και mantissa (μόνο το bit πρόσημου διαφέρει), το ±Infinity έχει bit εκθέτη όλα-ένα με ένα mantissa όλων των μηδενικών και το NaN έχει bit εκθέτη-ένα με τουλάχιστον ένα σύνολο εκθέτη. Όλα εδώ εκτελούνται τοπικά στο πρόγραμμα περιήγησής σας — τίποτα από όσα πληκτρολογείτε δεν μεταφορτώνεται πουθενά — γεγονός που το καθιστά ένα ασφαλές μέρος για να δημιουργήσετε πραγματική διαίσθηση για σφάλματα κινητής υποδιαστολής: γιατί «0.1 + 0.2 !== 0.3» σχεδόν σε κάθε γλώσσα προγραμματισμού, γιατί οι υφές float32 στον κώδικα γραφικών χάνουν την ακρίβεια που το float64 δεν θα έπρεπε.