איך אתם עושים את זה בשפה שלכם ?

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

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

כלומר אם ניקח את הפוסט הישן שלי של התרגיל הבא:

var c : Currency;
begin
C := 0.1 + 0.2;
writeln(C:2:2);
end.

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

10 מחשבות על “איך אתם עושים את זה בשפה שלכם ?

  1. ארתיום

    כך עושים את זה ב־C

    #include
    #include
    #include

    int main()
    {
    setlocale(LC_ALL,"");
    double c = 0.1 + 0.2;
    char buf[256];
    strfmon(buf,sizeof(buf),"%n",c);
    printf("%s\n",buf);
    }‎

    יש עיגול אוטומטי

    כך עושים את זה ב־C++‎ (קצת יותר מכוער):

    #include
    #include

    int main()
    {
    std::locale l("");
    std::cout.imbue(l);
    long price = 20+30; // agorot
    std::cout << std::showbase;
    std::use_facet<std::money_put >(l).put(std::cout,false,std::cout,' ',price);
    std::cout << std::endl;
    }‎

    שים לב שבשנייהם מקבלים (אם הלוקל הוא עברי) את הסימן ש"ח.

  2. shulamy

    אני לא מבין איך סטיה קטנה כזאת מפריעה לך.

    ואתהתמיד יכול לבדוק שההפרש קטן יותר ממה שאתה מרשה.

    איציק

    1. ik_5 מאת

      נראה אותך מחייב לקוח ב0.3 סנטים יותר ממה שהוא צריך לשלם.

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

    2. Shlomi Noach

      בנקים שסוחרים במיליארדי דולרים לא יכולים להרשות לעצם סטיות "קטנות" כאלה.
      בנוסף קורים דברים מוזרים שיוצרים טעויות של ממש.
      למשל, אתה עלול לגלות ש:
      4.0 + 1.0 < 5.0
      תשובה שגויה כזו עלולה למנוע מפקיד/ת הבנק שלך לאשר לך משיכה, משכנתא, וכו'.
      מתאים לך?

  3. Boris Shtrasman

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

  4. Shlomi Noach

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

  5. ארתיום

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

    ד"א ב־C++‎ זה קל מאוד ליצור מחלקה של מספרים "מדוייקים ועשים את העבודה המושלמת. כיצד? באותה צורה שיש ב־C++‎ והם לא חלק מהשפה אלא ספריה.

להשאיר תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s