ABA


"מה לא בסדר בקוד הבא ? ( שפת C )"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #11374 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 11374
Benayoun15
חבר מתאריך 7.6.02
1026 הודעות, דרג אמינות חבר זה
   21:22   19.11.04   
אל הפורום  
  מה לא בסדר בקוד הבא ? ( שפת C )  
 
   התוכנית קולטת סכום כסף
ומציגה כמה מטבעות של 10,5,1 ש"ח דרושים
וכמה מטבעות של 50,10,5,1 אגורות דרושים
מטבעות שלא בשימוש לא תכתבנה הודעות עלהם

הקטע הוא

https://rotter.name/User_files/nor/419e395434315ca2.txt


אני מכניס 12.19
והפלט הוא


Please enter an amount of money:
12.19
10 shekel coins needed:1
1 shekel coins needed:2
10 agorot coins needed:1
5 agorot coins needed:1
1 agorot coins needed:3

הטעות שהוא מציג 3 בסוף במקום 4 מטבעות של 1 אגורות


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  תעשה טבלת מעקב ותמצא טעות public_enemy 22.11.04 17:12 1
  אני אגיד לך. Dudenland 22.11.04 17:55 2
     תודה על ההסבר המפורט Benayoun15 23.11.04 23:49 3

       
public_enemy

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dudenland

דרג אמינות חבר זה
   17:55   22.11.04   
אל הפורום  
  2. אני אגיד לך.  
בתגובה להודעה מספר 0
 
   כמו שבוודאי ניתן לראות, השתמשת במשתנה מסוג double כדי לאחסן את סכום הכסף, ועם משתנה זה אתה מבצע מספר חישובים.
אני לא איכנס כאן לפרטי פרטים על אודות מימושו של הטיפוס double בשפת C. אני רק אזכיר כי מדובר במשתנה המיועד למספרים ממשיים "ארוכים" (בדיוק כפול), שמחולק ל-3 שדות, האחד מורה על הסימן (+/-), השני על המספר עצמו, והשלישי על החזקה שיש להכפיל בה את המספר (ומה שקובע את מיקום ה"נקודה הצפה"), וזאת כמובן ע"פ התקנים הסטנדרטים (IEEE).

אוקי, אז מה זה קשור בעצם?

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

אני מניח שזה עדיין לא ברור, אז בוא נעבור לדוגמה קלה.
נניח שאנחנו עובדים במערכת שבנוייה לפי בסיס 10, ושהשדה ששומר את המספר עצמו ב-double שומר עד 4 ספרות.
אם נרצה לייצג את המספר 19000 (מספר בן 5 ספרות), נייצג אותו כך שהמספר עצמו הוא 1900 (שוב, מגבלה של 4 ספרות), והחזקה היא 1 (כלומר נכפול ב-10 בחזקת 1). 1900 כפול 10 יוצא לנו 19000, כפי שרצינו.
ומה יקרה אם נרצה לייצג את המספר 19001? בגלל מגבלת 4 הספרות, ניקח את הספרות המשמעותיות ביותר (מצד שמאל), כלומר 1900, ונכפול בחזקה של 10 בחזקת 1. מה קיבלנו? 19000!!! כלומר איבדנו דיוק.

זהו לא בדיוק הייצוג של double, אך זוהי דוגמה קרובה מאוד, שממחישה לך על אודות תופעת איבוד הדיוק. תופעה זו קרתה אצלך בתכנית, בעיקר בגלל המרות מרובות שהיו לך בתכנית (בעיקר עם int וכו').

אם כך, למה כשעוקבים אחרי money מתקבלת תוצאה הגיונית?
מכיוון שהפונקציה printf מעגלת את הספרה האחרונה במספר. למעשה, בדוגמה שנתת, ערכו של money בחישוב האחרון הינו 0.0399999999 וכן הלאה, וכידוע לך, לאחר הכפלה ב-100 (לפי 100 אגורות בשקל), אתה מקבל 3.999999 ולאחר המרה ל-int, אתה מקבל 3, ולא 4.

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

אז מה לעשות?

1) אתה יכול להשתמש ב-float. המימוש שלו יותר פשוט, ומלווה בפחות אפשרויות לשגיאות מסוג זה, למרות ש-double יותר מדוייק.

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Benayoun15
חבר מתאריך 7.6.02
1026 הודעות, דרג אמינות חבר זה
   23:49   23.11.04   
אל הפורום  
  3. תודה על ההסבר המפורט  
בתגובה להודעה מספר 2
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net