(להשלים) ערכת לימוד בנושא כדי להבין שגיאות של נקודה צפה IEEE

כתב ויתור על תוכן KB שהוצא משימוש

מאמר זה נכתב על מוצרים ש- Microsoft כבר לא תומכת בהם. לכן, מאמר זה מוצע "כפי שהוא" והוא לא יעודכן עוד.

סיכום

נקודה צפה המתמטיקה הוא נושא מורכב המבלבלת מתכנתים רבים. ערכת הלימוד שלהלן יסייע לך לזהות מצבים תיכנות שבהן הם שגיאות של נקודה צפה עלולה להתרחש וכיצד להימנע מהן. הוא גם אמור לאפשר לך לזהות אירועים הנגרמות בשל מגבלות מתמטיקה של נקודה צפה האופייניים בניגוד באגים מהדר בפועל.

מידע נוסף

מערכות מספרים עשרוניים ו בינארי

בדרך כלל, אנו לספור דברים בבסיס 10. הבסיס הוא שרירותי לחלוטין. הטעם היחיד אנשים באופן מסורתי שהשתמשת בבסיס 10 הוא שתהיה להם אצבעותיך 10, הפכו את כלי ספירה בהישג יד.


המשמעות של מספר 532.25 בתבנית עשרונית (בסיס 10) הבאות:

   (5 * 10^2) + (3 * 10^1) + (2 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
500 + 30 + 2 + 2/10 + 5/100
_________
= 532.25


במערכת המספרים הבינארית (בסיס 2), כל עמודה מייצגת בחזקת 2 במקום 10. לדוגמה, המספר 101.01 מציין את הפעולות הבאות:

   (1 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2)
4 + 0 + 1 + 0 + 1/4
_________
= 5.25 Decimal


כיצד מספרים שלמים שאינם מיוצגים במחשבים אישיים

מכיוון שאין אין שבר שלם, ייצוג המחשב שלו הוא לפשוטים הרבה יותר מאשר הוא עבור ערכי נקודה צפה. מספרים שלמים רגילה במחשבים אישיים (אישיים) הם 2 בתים (16 סיביות) ארוך עם הסיבית החשובה המציין את הסימן. שלמים ארוכים הם באורך של 4 בתים. ערכים חיוביים הם מספרים בינאריים פשוטה למדי. לדוגמה:

    1 Decimal = 1 Binary
2 Decimal = 10 Binary
22 Decimal = 10110 Binary, etc.


עם זאת, מספרים שלמים שליליים מיוצגים על-ידי שימוש בערכת המשלים שני. כדי לקבל המשלים ייצוג של שני עבור מספר שלילי, קח ייצוג בינארי עבור הערך המוחלט של המספר ולאחר מכן הפוך את הסיביות והוסף 1. לדוגמה:

   4 Decimal = 0000 0000 0000 0100
1111 1111 1111 1011 Flip the Bits
-4 = 1111 1111 1111 1100 Add 1


שים לב-1 זה עשרוני = 1111 1111 1111 1111 בינארי, המסביר מדוע Basic מתייחס-1 כ- true לוגי (כל הסיביות = 1). זוהי תוצאה של המנעות אופרטורים נפרד עבור השוואות bitwise ולוגית. לעתים קרובות ב- Basic, הוא נוח לשימוש קטע קוד מתחת כאשר התוכנית שלך אפשרות ביצוע השוואות לוגיות רבות. הדבר מסייע מאוד קריאות.

   CONST TRUE = -1
CONST FALSE = NOT TRUE


הערה המשלימים הוספת כל שילוב של שני המספרים יחד באמצעות פעולות אריתמטיות בינארי רגיל מפיק את התוצאה הנכונה.

סיבוכים נקודה צפה

ניתן לייצג כל מספר שלם עשרוני בדיוק על-ידי מספר בינארי שלם; עם זאת, זה לא נכון עבור מספרים עם שברים. למעשה, כל מספר irrational בבסיס 10 תהיה irrational במערכת כלשהי עם בסיס קטן מ- 10.


עבור בינארי, בפרט, מספרים עם שברים בלבד אשר ניתן לייצג את הטופס p/q, כאשר q הוא בחזקת מספר שלם 2, ניתן לבטא בדיוק, עם מספר סופי של bits.


גם שברים עשרוניים נפוצים, כגון 0.0001 בבסיס עשרוני, לא ניתנים לייצוג מדויק בתבנית בינארית. (0.0001 הוא שבר בינארי שחוזר על בפרקים של 104 סיביות)!


זה מסביר מדוע דוגמה פשוטה, למשל הפרטים הבאים

   SUM = 0
FOR I% = 1 TO 10000
SUM = SUM + 0.0001
NEXT I%
PRINT SUM ' Theoretically = 1.0.


יהיה 1.000054 הדפסה כפלט. השגיאה הקטנה בייצוג 0.0001 בתבנית בינארית מתפשטת לסכום.


מאותה סיבה, עליך תמיד להיות זהיר מאוד בעת ביצוע השוואות על מספרים ממשיים. הדוגמה הבאה מדגימה את שגיאת תיכנות נפוצות:

   item1# = 69.82#
item2# = 69.20# + 0.62#
IF item1# = item2# then print "Equality!"


פעולה זו לא יודפס "שוויון!" מכיוון 69.82 לא ניתנים לייצוג מדויק בתבנית בינארית, הגורמת ערך הנובע מתוך ההקצאה יהיה שונה במקצת (בספרות בינאריות) מאשר ערך שנוצר מביטוי. בתרגול, תמיד עליך לקודד השוואות כאלה באופן כזה המאפשר עבור הרגישות מסוימים. לדוגמה:

   IF (item1# < 69.83#) AND (item1# > 69.81#) then print "Equal"


הדבר יגרום להדפסת "שווה".

עיצוב IEEE מספרים

QuickBasic עבור MS-DOS, גירסה 3.0 שהגיע עם גירסה מגש הזנת מעקף (נקודת Floating בינארי של Microsoft) לבין גירסה IEEE (מכון חשמל ומהנדסי אלקטרוניקה) עבור מחשבים עם מעבד עזר מתמטי. QuickBasic עבור MS-DOS, גירסאות 4.0 ואילך להשתמש רק IEEE. Microsoft בחרה בתקן IEEE כדי לייצג ערכי נקודה צפה בגירסאות נוכחיות של בסיסי מהסיבות ראשי שלוש הבאות:

  1. כדי לאפשר Basic לשימוש coprocessors מתמטיקה Intel, שבו השתמש בתבנית IEEE. Coprocessors 80 x 87 סידרה של Intel אין אפשרות לעבוד עם מספרים בתבנית בינארית של Microsoft.
  2. כדי להפוך interlanguage מתקשר בין בסיסי, C, פסקל, פורטרן, MASM קלה בהרבה. אחרת, רוטינות ההמרה יצטרך לשמש לשליחת ערכים מספריים משפה אחת לאחרת.
  3. כדי להשיג את העקביות. IEEE הוא המקובל בתעשייה רגיל עבור יוצרי האוסף C ופורטרן.
הפקודה באה מדגימה השוואה מהירה של ייצוגי IEEE ומגש הזנת מעקף עבור מספר דיוק כפול:

               Sign Bits   Exponent Bits   Mantissa Bits
--------- ------------- -------------
IEEE 1 11 52 + 1 (Implied)
MBF 1 8 56


לקבלת מידע נוסף אודות ההבדלים בין IEEE ומגש הזנת מעקף הנקודה הצפה ייצוג, השאילתה ב- Microsoft Knowledge Base על המילים הבאות:

   IEEE and floating and point and appnote


שים לב כי IEEE יש יותר סיביות ייעודי המעריך, תכונה המאפשרת לו לייצג מגוון רחב יותר של ערכים. מגש הזנת מעקף יש סיביות המנטיסה יותר, מה שמאפשר שהיא תהיה מדויקת יותר בטווח צר יותר שלו.

מושגים נקודה צפה כללי

חשוב מאוד שמת לב כי כל נקודה צפה מערכת בינארית לייצג רק מספר מוגבל של ערכי נקודה צפה בצורה מדויקת. ניתן לקרב את ערכיהן של כל הערכים האחרים לפי הערך ניתן לייצוג הקרוב ביותר. תקן IEEE מציין את שיטת לעיגול ערכי לערך ניתן לייצוג "הקרוב ביותר". QuickBasic עבור MS-DOS תומך הרגילה ועיגול לפי הכללים IEEE.


כמו כן, זכרו המספרים יכול להיות מיוצג ב- IEEE הם לאורך טווח רחב מאוד. ניתן לדמיין אותם על קו מספר. אין צפיפות גבוהה ניתן לייצוג מספרים ליד 1.0 ו--1.0 אך פחות פחות בעת מעבר כלפי 0 או אינסוף.


המטרה של תקן IEEE, המיועדת עבור הנדסה חישובים, היא להגדיל את הדיוק (כדי להגיע קרוב ככל האפשר בפועל מספר). דיוק מתייחס למספר הספרות היכול לייצג. תקן IEEE מנסה לאזן את מספר הסיביות ייעודי המעריך עם מספר הסיביות המשמשות עבור חלק השבר של המספר, כדי לשמור על דיוק ודיוק בתוך גבולות קביל.

פרטי IEEE

מספרי נקודה צפה מיוצגים בצורה הבאה, כאשר [המעריך] הוא המעריך הבינארי:

   X =  Fraction * 2^(exponent - bias)


[] Fraction מנורמל חלק השבר של המספר, לנרמל מכיוון המעריך מותאם כך הסיבית המובילה תהיה תמיד 1. בדרך זו, אין לו אפשרות לאחסון, וקבל סיבית אחת יותר של דיוק. זו הסיבה שבגללה ישנה סיבית משתמעת. ניתן לחשוב על זה כמו מדעי, שבו ניתן להגדיר את המעריך כך שיכלול ספרה אחת משמאל לנקודה העשרונית, למעט בסיס בינארי, שתמיד ניתן להגדיר את המעריך כך הראשונה תהיה 1, מאחר שקיימים רק 1s ו- 0.


[הפרש] הוא ערך הסטייה המשמש כדי למנוע את הצורך באחסון מעריכים שליליים.


הפרש עבור מספרים בעלי דיוק יחיד היא 127 ועבור 1023 (עשרוני) עבור מספרים בעלי דיוק כפול.


הערכים שווה ל- 0 כל ואת כל 1 של (בינאריים) שמורות המייצג מקרים מיוחדים. ישנם אחרים במקרים מיוחדים, גם לציין תנאי שגיאה שונות.

דוגמאות של דיוק יחיד

1 = 2 * 2 ^ 1 = 0100 0000 0000 0000... hex 0000 0000 = 4000 0000
שים לב סיבית הסימן הוא אפס, והוא המעריך מאוחסנת 128, או 100 0000 0 בתבנית בינארית, היא 127 בתוספת 1. המנטיסה מאוחסנת הוא (1) 000 0000... 0000 0000, שבו יש משתמעת מוביל 1 ו בינארי נקודת, כך המנטיסה בפועל הוא 1.

-2 =-1 * 2 ^ 1 = 1100 0000 0000 0000... 0000 0000 = C000 0000 hex
בדומה +2 למעט העובדה הגדרת היא סיבית הסימן. הדבר נכון לגבי כל IEEE עיצוב נקודה צפה מספרים.

4 = 1 * 2 ^ 2 = 0100 0000 1000 0000... hex 0000 0000 = 4080 0000
המנטיסה זהה, המעריך מגדילה אחת (ערך biased הוא 129, או 1 0000 100 בתבנית בינארית.

6 = 1.5 * 2 ^ 2 = 0100 0000 1100 0000... 0000 0000 = 40C 0 0000 משושה
מעריך אותו, המנטיסה אינו גדול יותר על-ידי חצי--הוא (1) 100 0000... 0000 0000, שהיא, מאחר שזוהי שבר בינארי, 1-1/2 (הערכים של ספרות השברים הם 1/2, 1/4, 1/8, וכן הלאה.).

1 = 1 * 2 ^ 0 = 0011 1111 1000 0000... Hex 0000 0000 = 3F80 0000
הוא המנטיסה מעריך אותו בתור אחרים חזקות של 2, אחת פחות מ- 2 127, או 1 1111 011 בתבנית בינארית.

.75 = 1.5 * 2 ^-1 = 0011 1111 0100 0000... Hex 0000 0000 = 3F40 0000
הוא המעריך biased 126, 011 1111 בינארי ב- 0 ולאחר המנטיסה הוא (1) 100 0000... 0000 0000, שהוא 1-1/2.

2.5 = 1.25 * 2 ^ 1 = 0100 0000 0010 0000... hex 0000 0000 = 4020 0000
זהה כפי 2 למעט אשר הסיבית המייצג 1/4 מוגדרת במנטיסה.

0.1 = 1.6 * 2 ^-4 = 0011 1101 1100 1100... 1100 1101 = 3DCC CCCD משושה
1/10 הוא שבר חוזר בתבנית בינארית. המנטיסה הוא פשוט shy של 1.6 והמעריך biased אומר 1.6 הוא אפשרות לחלוקה על-ידי 16 (הוא 1 1101 011 בינארי, שהוא 123 בשיטה העשרונית). אמת המעריך 123-127 = - 4, כלומר הפקטור שבו יש להכפיל הוא 2 * *-4 = 1/16. שים לב המנטיסה מאוחסנת מעוגל כלפי מעלה בהסיבית האחרונה. זהו ניסיון כדי לייצג מספר unrepresentable במדויק ככל האפשר. (הסיבה 1 ו- 1/10/100 הם לא בדיוק ניתן לייצוג בינארי דומה לאופן 1/3 הוא לא בדיוק ניתן לייצוג העשרוני.)

0 = 1.0 * 2 ^-128 = אפסים - מקרה מיוחד.

שגיאות נקודה צפה נפוצות אחרות

להלן נקודה צפה שגיאות נפוצות:

  1. שגיאות עיגול


    שגיאה זו נובעת כאשר אין אפשרות להשתמש כל הסיביות במספר הבינארי בחישוב.


    דוגמה: הוספת 0.0001 מציין כדי 0.9900 (דיוק יחיד)


    0.0001 בבסיס עשרוני ייוצג:
    (1) 10100011011011100010111 * 2^(-14+Bias) (13 מובילים 0s בינארי!)
    0.9900 ייוצג:
    (1.)11111010111000010100011 * 2^(-1+Bias)
    כעת למעשה להוסיף מספרים אלה, נקודות עשרוניות (בינאריים) חייב להיות מיושרים. לשם כך הם חייבים להיות Unnormalized. הנה התוספת שנוצר:
           .000000000000011010001101 * 2^0  <- Only 11 of 23 Bits retained
    +.111111010111000010100011 * 2^0
    ________________________________
    .111111010111011100110000 * 2^0


    פעולה זו נקראת שגיאת עיגול מכיוון שחלק מהמחשבים לעגל בעת הנעה עבור תוספת. אחרים פשוט לחתוך. שגיאות עיגול חשובות שיש להביא בחשבון בכל פעם שאתה מוסיף או הכפלת שני ערכים שונים מאוד.
  2. שני והפחתת כמעט שווים לערכים
           .1235
    -.1234
    _____
    .0001


    זו לנרמל. שים לב כי למרות המספרים המקורית כל היה ארבע ספרות משמעותיות, התוצאה כוללת ספרות משמעותיות אחד בלבד.
  3. גלישה ומחסור


    דבר זה מתרחש כאשר התוצאה היא גדול מדי או קטן מכדי להיות מיוצג על-ידי סוג הנתונים.
  4. שגיאה quantizing


    בעיה זו מתרחשת עם מספרים אלה להיות מיוצגת בצורה מדויקת לפי תקן נקודה צפה.
  5. חילוק על-ידי מספר קטן מאוד


    פעולה זו עשויה לגרום לשגיאת "חלוקה באפס" או עשוי לגרום לתוצאות שגוי, כמו בדוגמה הבאה:
          A = 112000000
    B = 100000
    C = 0.0009
    X = A - B / C


    ב- QuickBasic עבור MS-DOS, X כעת יש את הערך 888887, במקום התשובה הנכונה, 900000.
  6. שגיאת פלט


    סוג זה של שגיאה מתרחשת כאשר פונקציות פלט לשנות את הערכים שהם עובדים עם.
מאפיינים:

מזהה פריט: 42980 - סקירה אחרונה: 17 בינו׳ 2017 - תיקון: 1

משוב