0

IEEE-754 Float Visualizer

ראה בדיוק כיצד מאוחסן מספר עשרוני בתור IEEE-754 float - סיביות סימנים, סיביות מעריך וסיביות מנטיס - ומדוע מספרים כמו 0.1 אינם מאוחסנים בדיוק.

Buy Me a Coffee at ko-fi.com
מעבד... 0%
מנרמל
הטיית מעריכי מחשוב
פיסות מנטיס מתרחבות
בוצע

תוצאה

כל מספר נקודה צפה שמחשב מאחסן - מספר JavaScript, צף C, צף פייתון - מקודד באותו אופן תחת IEEE 754: סיביות סימן אחת, בלוק של סיביות מעריך ובלוק של סיביות מנטיסה (שבר). דיוק יחיד (32 סיביות) משתמש בסיבית סימן 1, 8 סיביות מעריך ו-23 סיביות מנטיס; דיוק כפול (64 סיביות), הפורמט שמאחורי סוג מספר ברירת המחדל של כמעט כל שפה, משתמש בביט סימן אחד, 11 סיביות מעריך ו-52 סיביות מנטיס. הכלי הזה לוקח כל מספר עשרוני שאתה מקליד, מקודד אותו בכל אחד מהרוחבים באמצעות מקודד ה-DataView/ArrayBuffer הצף של הדפדפן - אותה מכונות שהקוד שלך פועל עליה בפועל - וצובע כל סיביות לפי האזור שאליו הוא שייך.

הקידוד עצמו עוקב אחר שלושה שלבים, והכלי הזה עובר על כולם במקום רק להציג את הסיביות הסופיות. ראשית, נורמליזציה: המספר נכתב מחדש כ-1.mantissa × 2^exponent, עם ספרה אחת שאינה אפס בדיוק לפני הנקודה הבינארית (מספרים קטנים מדי בשביל זה מקבלים את הטיפול התת-נורמלי במקום זאת, ללא 1 מוביל מרומז). שנית, הטיית מעריך: מכיוון ששדה המעריך חייב לאחסן מעריכים חיוביים ושליליים כמספר ללא סימן, הטיה קבועה (127 עבור דיוק יחיד, 1023 עבור כפול) מתווספת לפני שהשדה נכתב בבינארי. שלישית, המנטיסה השברית מורחבת טיפין טיפין עם השיטה הקלאסית "הכפילו בשניים, קח את החלק השלם כסיביות הבאות, שמור את השאר" - חוזרת על עצמה עד ששדה המנטיסה מלא, ובשלב זה הסיביות שנשארו מחליטות אם התוצאה מתעגלת למעלה או למטה (מעגל-חצי לא-שוויון, ברירת המחדל של IEEE-754).

זו בדיוק הסיבה שמספר רגיל כמו 0.1 לא מאוחסן בדיוק. בבינארי, 0.1 הוא שבר שחוזר על עצמו (0.0001100110011... לנצח), כך שאף מנטיסה סופית לא יכולה להחזיק אותו במדויק - יש לעגל אותו איפשהו. קודדו 0.1 כ-float של 32 סיביות וקרא את הביטים בחזרה, ואתה לא מקבל 0.1 בחזרה: אתה מקבל בדיוק 0.100000001490116119384765625. לדיוק כפול יש עוד 29 סיביות מנטיס לעבוד איתם, כך שגיאת העיגול שלו קטנה בהרבה, אבל היא גם לא אפס - 0.1 ככפול של 64 סיביות הוא בדיוק 0.1000000000000000005551115123125782702102154525410101545254101. הכלי הזה מחשב את הערך המאוחסן המדויק עם אריתמטיקה של מספרים גדולים (ללא קיצורי דרך של נקודה צפה) כך שהפער בין מה שהקלדת לבין מה שהחומרה שומרת בפועל לעולם אינו מוסתר או משוער.

ערכים מיוחדים מקבלים דפוסי סיביות מדויקים ושמורים במקום קידוד רגיל: לאפס ואפס שלילי יש סיביות אקספוננט ומנטיסה אפסיים (רק סיביות הסימן שונה), ±Infinity כוללת סיביות מעריך הכל אחד עם מנטיס הכל-אפס, ול-NaN יש סיביות מעריכי הכל-אחד עם ביט מנטיס אחד לפחות. הכל כאן פועל באופן מקומי בדפדפן שלך - שום דבר שאתה מקליד לא מועלה לשום מקום - מה שהופך את זה למקום בטוח לבניית אינטואיציה אמיתית עבור באגים של נקודה צפה: למה `0.1 + 0.2 !== 0.3` כמעט בכל שפת תכנות, מדוע מרקמי float32 בקוד גרפי מאבדים את הדיוק ש-float64 לא היה אמור להמנע מנקודה פיננסית בכלל, ולמה קוד פיננסי בכלל לא היה צריך לצוף.