DCSIMG
Question from Tapuz .Net forum: Dividing operators are not what you thought - Justin myJustin = new Justin( Expriences.Current );

Question from Tapuz .Net forum: Dividing operators are not what you thought

שאלה:

אני רוצה לחלק 5/3 ולקבל את הערך המלא כלומר גם מה שמאחורי הנקודה העשרונית אפשר אולי להראות לי איך?

 

תשובה:

בואו נראה איך נראית חלוקה רגילה של למשל 6 ו-3.

            int result = 6/3;

            Console.WriteLine(result);

image 

כצפוי, התשובה היא 2.

עכשיו בואו נשתמש באותה תבנית ונחלק 5 ב-3.

            int intResult = 5/3;

            Console.WriteLine(intResult);

image

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

אמרו בפורום להמיר את התוצאה ל-double (או float) ואז נקבל את התוצאה הנכונה.

            double doubleResult1 = 5/3;

            Console.WriteLine(doubleResult1);

image

זה לא עזר - עדיין קיבלנו 1.

עכשיו בואו ננסה להמיר את שתי האגפים שלנו ל-double. (גם התוצאה וגם התרגיל)

            double doubleResult2 = (double) 5/(double) 3;

            Console.WriteLine(doubleResult2);

image

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

כלומר, גם אם לחלוקה יש שארית, לא נקבל אותה כחלק מהמספר, ובחלוקה של intים תמיד יש סטייה של עד כדי שלם אחד מהתוצאה האמיתית.
אבל בחלוקה של doubleים או כל טיפוס מספרי אחר שמסוגל להכיל Precision ו-Scale אחרי הנקודה העשרונית - כן נקבל את שארית החילוק.

עכשיו השאלה המעניינת היא למה זה?

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

נביט על מה כתוב ב-C# Language Spec על ההתנהגות הזו:
http://msdn2.microsoft.com/en-us/library/aa691373(vs.71).aspx

image

image

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

אבל מה באמת מעניין בזה?
שעבורנו שאנחנו רואים בעין 3\5 זה בדיוק אותו דבר כמו 3.0\5.0.
אנחנו רואים הבדל במספרים (בגלל הנקודה עשרונית), אבל הסימן חילוק הסלאש הימני נראה לנו בדיוק אותו דבר.

זה לא אותו סימן!
סלאש ימני של חילוק בין טיפוסים שונים הוא לא אותו אופרטור! זה קוד שונה לחלוטין שרץ מאחורי הקלעים.
זה שהסימן / נראה אותו דבר זה לא אומר שמדובר באותו אופרטור.

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

            double doubleResult3 = 5 / (double)3;

            Console.WriteLine(doubleResult3);

            double doubleResult4 = (double)5 / 3;

            Console.WriteLine(doubleResult4);

image

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

המסקנה שלי וה-Best Practice היא - שמחלקים שני Intים ממירים את שניהם ל-decimal ומחזירים את התוצאה ל-decimal.
(אישית אני מעדיף לעבוד רק אם Int32 ו-decimal כטיפוסים מספריים, אבל זאת העדפה אישית)

קישור: http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=105840781

Published Monday, October 15, 2007 3:34 PM by Justin-Josef Angel [MVP]
תגים:, ,

Comments

No Comments