Question from Tapuz .Net forum: Dividing operators are not what you thought
שאלה:
אני רוצה לחלק 5/3 ולקבל את הערך המלא כלומר גם מה שמאחורי הנקודה העשרונית אפשר אולי להראות לי איך?
תשובה:
בואו נראה איך נראית חלוקה רגילה של למשל 6 ו-3.
כצפוי, התשובה היא 2.
עכשיו בואו נשתמש באותה תבנית ונחלק 5 ב-3.
רגע, מה? 5 חלקי 3 זה לא 1.
אני זוכר בבירור שחווה הגננת אמרה שזה יותר מתפוח אחד ופחות משני תפוחים.
אמרו בפורום להמיר את התוצאה ל-double (או float) ואז נקבל את התוצאה הנכונה.
זה לא עזר - עדיין קיבלנו 1.
עכשיו בואו ננסה להמיר את שתי האגפים שלנו ל-double. (גם התוצאה וגם התרגיל)
מסתבר, שחלוקה של שני intים תמיד תחזיר int מעוגל כלפי מטה.
כלומר, גם אם לחלוקה יש שארית, לא נקבל אותה כחלק מהמספר, ובחלוקה של intים תמיד יש סטייה של עד כדי שלם אחד מהתוצאה האמיתית.
אבל בחלוקה של doubleים או כל טיפוס מספרי אחר שמסוגל להכיל Precision ו-Scale אחרי הנקודה העשרונית - כן נקבל את שארית החילוק.
עכשיו השאלה המעניינת היא למה זה?
מה מסתבר? הכל עניין של איזה טיפוסים ננסה לחלק.
אם ננסה לבצע תרגיל שאין לו נקודה עשרונית - נקבל תוצאה בלי נקודה עשרונית.
אם ננסה לבצע תרגיל עם נקודה עשרונית - נקבל תוצאה עם נקודה עשרונית.
נביט על מה כתוב ב-C# Language Spec על ההתנהגות הזו:
http://msdn2.microsoft.com/en-us/library/aa691373(vs.71).aspx
אז מסתבר שרק חלוקה של שני אגפים מאותו טיפוס תחזיר את הטיפוס הרלוונטי.
אבל מה באמת מעניין בזה?
שעבורנו שאנחנו רואים בעין 3\5 זה בדיוק אותו דבר כמו 3.0\5.0.
אנחנו רואים הבדל במספרים (בגלל הנקודה עשרונית), אבל הסימן חילוק הסלאש הימני נראה לנו בדיוק אותו דבר.
זה לא אותו סימן!
סלאש ימני של חילוק בין טיפוסים שונים הוא לא אותו אופרטור! זה קוד שונה לחלוטין שרץ מאחורי הקלעים.
זה שהסימן / נראה אותו דבר זה לא אומר שמדובר באותו אופרטור.
ביינתים, בזמן שאני כותב את התשובה הזו, אמרו בפורום שאפשר גם לחלק רק באגף אחד מאותו טיפוס ועדיין נקבל מספר עם נקודה עשרונית. למשל:
אז למה זה קורה אם אמרנו ששני האגפים צריכים להיות מהטיפוס וזה מה שכתוב בתיעוד?
כי רק אופרטור אחד יתאים לתיאור של חלוקה של double באיבר אחר (או עם איבר אחר) והאיבר השני (שבמקרה שלנו הוא Int32) יומר אוטומטית ל-double.
המסקנה שלי וה-Best Practice היא - שמחלקים שני Intים ממירים את שניהם ל-decimal ומחזירים את התוצאה ל-decimal.
(אישית אני מעדיף לעבוד רק אם Int32 ו-decimal כטיפוסים מספריים, אבל זאת העדפה אישית)
קישור: http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=105840781