הודעת אזהרה בסי ++

epsilonnow

New member
הודעת אזהרה בסי ++

יש לי קטע קוד לחישוב שטח של משולש ואני מקבל מה VISUAL C הודעת אזהרה של המרת DOUBLE ל FLOAT ואיבוד חלק מהספרות. אז אם מישהו יכול לפרט מה ההודעה ואיך אפשר לפתור אותה בלי לשנות את ההחזרה של הפונקציה ל DOUBLE (חשוב לי שהיא תשאר FLOAT).
float triangle::area() { return (sqrt(3)*pow(a,2))/8.0; }​
 

זהיר

New member
הבג הוא בהחזרת FLOAT

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

epsilonnow

New member
הסיבה הממש טובה לא כל כך טובה

בסה"כ הגדרות של פונקציות שקיבלתי כשיעורי בית ולא רציתי לשנות את הכותרות. ניסיתי להוסיף את התו F אחרי פעולת החישוב או לרשום (float) לפניו, כמו כן שים לב שרשום 8.0 ולא סתם 8 , וכל זה על מנת לבצע casting אבל משום מה זה עדיין נותן לי את אותה ההודעה. חוצמיזה, ממה נובעת הזהירות הגדולה ("תוודא שאתה יודע מה שאתה עושה") ? אני יכול לגרום פה איזשהו נזק ???
 

זהיר

New member
כל WARNING מסמן בג פוטנציאלי

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

voguemaster

New member
להיפך יקירי

צריך סיבה ממש ממש טובה כדי לעבוד עם double. למעשה, float רגיל נותן לך את כל הדיוק שלו אתה צריך בכמעט כל דבר שהוא, וטווח המספרים די גדול. רק אם אתה צריך ייצוג של מספרים ממשיים הרבה יותר גדולים שווה לעבוד עם double, אחרת כמעט ואין טעם. אפילו במודלים נומריים לא ממש שומרים מעבר ל-6 מקומות אחרי הנקודה אז כל הטיעונים של "דיוק" הם די מפגרים. ודבר נוסף, כמו שאמרתי, מבחינת ביצועים float עדיף. לא יעזור, זה פשוט מאפשר לטעון יותר floatים ל-cache במכה אחת וזה שווה את זה בביצועים. בגלל זה משתמשים ב-float בהרבה מנועים תלת מימדיים. ואני מכיר את הטיעון שלך שגם ככה float שנטען לרגיסטר של ה-FPU הופך ל-double. זה נכון. זה לא משנה את העובדה שאפשר להכפיל את הכמות שטוענים, מה גם שההמרה הזו לא עולה כלום כמעט.
 

Zack DA

New member
../images/Emo45.gif כמו כן זה נחמד שהקומפיילר צועק

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

voguemaster

New member
על מה כבודו מדבר ?

אני מדבר על ההמרה שמתבצעת כשערך float נכנס לרגיסטר של ה-FPU, אין לזה חצי קשר לטיפוסי המשתנים ולקומפיילר. לצורך העניין, אם הקומפיילר מייצר לך קוד שמשתמש בפקודות של המעבד המתימטי, ואתה עובד *רק* עם float ואין לך שום cast ושום נעליים, עדיין מתבצעת המרה ברמת החומרה בין float ל-double כי גודלו של כל רגיסטר של ה-FPU הוא 8 בתים. שוב, זה לא קשור ל-cast ב-C, ממש לא.
 

זהיר

New member
קומפיילר טוב יזהיר

כשיש המרה שבה דיוק הולך לאיבוד (למשל מ DOUBLE ל FLOAT) אפילו אם הטיפוס של X הוא FLOAT, הטיפוס של X + 2.3 הוא DOUBLE (ואידך, זיל גמור)
 

voguemaster

New member
חבר'ה אתם לא מבינים מה אני מנסה

להגיד. הפואנטה שלי פשוטה מאוד: עדיף לעבוד עם float. מעט מאוד דברים צריכים את הדיוק של double ומבחינת ביצועים זה עדיף, במידה וזה משמעותי (כמו במנועים תלת מימדיים מסוימים). עכשיו, בנוגע להמרות: אני דיברתי חד משמעית על המרה מ-float ל- double. לא להיפך! ההמרה לא מתבצעת ברמת הקוד ב-C. מבחינתך כשאתה נניח מנסה לשנות משתנה float כלשהו ולבצע עליו מניפולציה כלשהי, הוא נטען לרגיסטר של ה-FPU. עצם הטעינה הוא המרה מ-float ל-double. הקומפיילר אומנם הוא זה שמייצר את הפקודה שטוענת את הערך לרגיסטר אבל זה לא ממש משנה. אין שום דיוק שהולך לאיבוד בגלל שאתה טוען float לתוך רגיסטר שמכיל double. בכל אופן... נדמה לי שברמה הנורמלית של אזהרות הקומפיילרים השונים לא מזהירים מהמרה של float ל-double. ואגב, הטיפוס של: float x = 1.0f; float f = x + 2.3f; // type if float הקומפיילר גם מבין היטב שהוא צריך לייצר float בסוף, אין פה בכלל משחק עם double...
 

Zack DA

New member
לא משנה, יתכן שיש דיוק שאובד

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

voguemaster

New member
אני דיברתי

ספציפית על המרה מ-single ל-double precision. ההמרה מבוצעת ע"י ה-FPU בצורה פנימית, אפילו שהקומפיילר הוא זה שמייצר את הוראת האסמבלי שטוענת את הערך לרגיסטר. בכלל לא דיברתי על ההמרה מ-double ל-single. ונדמה לי שעם אזהרות מלאות אתה גם מקבל אזהרה כשאתה ממיר מ-single ל-double...
 

זהיר

New member
Don't "dear" me, please ../images/Emo98.gif

3D יכול להחשב כסיבה טובה, אבל גם אם בזה אתה עוסק, לא כל העולם 3D. אצל רוב המתכנתים תקבל משהו בסגנון
מספר לא "בינארי" // float x = 1.3; if (x == 1.3) { // will return FALSE for most values // DO something } else { // x is not that value }​
סע לשלום, הבג כבר בפנים (וכדי לחסוך ויכוח מיותר, אני יודע על מקרים אמיתיים (לא תרגיל ביצפר) שדבר כזה קרה).
 

אלדד28

New member
אבל הדוגמה הזו ספציפית

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

voguemaster

New member
אמממ

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

זהיר

New member
ערבבתם שני דברים

(גם אלדד28 וגם VOGUEMASTER) בהינתן DOUBLE X = 1.3 אפשר תמיד לסמוך על ההשוואה X == 1.3 (K&R2 A.6.4). זה נכון שאי אפשר לסמוך על ההשוואה X + X == 2.6. אבל אם X הוא FLOAT אי אפשר לסמוך אפילו על המקרה הראשון (אבל אפשר לסמוך על ההשוואה X == 1.3F). זה מסביר מה הסיבה הבסיסית שלי: DOUBLE הוא הטיפוס ה"בסיסי" של C עבור FP TYPES (כמו ש INT עבור שלמים), אם אתה משתמש בקבוע ורוצה טיפוס אחר אתה חייב להגיד את זה (F או L, כ SUFFIX) - זו מלכודת עבור המתכנתים שלך (חוק מרפי). תכנתו בזהירות
 
למעלה