חשבון פשוט בשפת C ...

נתן.ל

New member
חשבון פשוט בשפת C ...

יש לי מספר בFLOATE ואני מכפיל אותו במאה ומכניס אותו אל תוך INT ... משום מה לא תמיד 12.12 יוצא 1212 לפעמים קורה ש23.23 יוצא 2322 ... למה זה קורה ?
unsigned int t; float n=23.23; t = (int)(n*100); printf("t=%d \n",t);​
איך אפשר להתגבר על זה ? אני רוצה להפוך מספר F עם שתי ספרות אחרי הנקודה למספר INT מוכפל במאה ולא לאבד ספרות בדרך ... למה זה לא קורה ?
 

jgut

New member
double

אין לי מושג ב- float . אבל תנסה להגדיר את n בתור double. בצורה שבה זה כתוב כרגע מתקבלת ההודעה : warning C4305: ´initializing´ : truncation from ´const double´ to ´float´.
 

yair24

Member
אני פתרתי את זה כך:

#include<stdio.h> void main() { int it; float n=23.23,t; t=n*100; it=(int)t; printf("%d\n",it); }​
ניסיתי להבין למה זה קורה אבל לא הצלחתי להבין אם מישהו יודע אני אשמח גם כן לשמוע... אבל מה שעשיתי פה עובד. יאיר
 

albanetc

New member
או ככה...

בתוכנה המקורית לכתוב 100.0 במקום 100 וזהו.
 

yair24

Member
ניסיתי משהו דומה וזה לא עבד...

אני ניסיתי להכפיל את 100 ב1.0 100*1.0 וזה פשוט לא עבד אני אנסה את מה שאמרת ונראה... ולמה זה קורה אתה יודע? יאיר
 

albanetc

New member
קורה...

אפשר גם:
int i = (int) (float) (f * (float) 100.0);​
ושייחנק...
 

נתן.ל

New member
../images/Emo51.gif ../images/Emo51.gif ../images/Emo51.gif

פועל מצויין
 

yair24

Member
בבקשה... ../images/Emo13.gif

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

עידית_

New member
למה זה קורה?

הסיבה היא שיטת היצוג של מספרים ממשיים כ-floating point במחשב. מתוך MSDN:
Floating point decimal values generally do not have an exact binary representation. This is a side effect of how the CPU represents floating point data. For this reason, you may experience some loss of precision, and some floating point operations may produce unexpected results.​
מי שרוצה להבין יותר לעומק, אני מצרפת גם לינק שמסביר את שיטת היצוג של float (אמנם מדובר שם על ה-JVM אבל זה אותו תקן IEEE שכולם פחות או יותר משתמשים בו). ולמי שמתעצל אפשר להגיד (בניסוח פשטני), שביצוג בינארי, בדיוק כמו ביצוג העשרוני הרגיל, לא כל מספר ממשי אפשר לייצג באופן מדויק במספר סופי של ספרות. כתוצאה מכך כמעט תמיד תיתקלו בבעיות כאלה כשתעבדו עם float...
 

aviharus

New member
אי אפשר

שפת C מאפשרת לבצע המרה בין משתנים שלא מאותו סוג. אם אתה ממיר ממספר שיכול להכיל FLOATING POINT כמו FLOAT למספר קטן כמו INT בטוח שתאבד את החלק העשרוני .לכן בד"כ המרה תעשה מהקטן לגדול ולא להיפך
 

עידית_

New member
זה נכון מאוד, אבל

הבעיה יותר מורכבת מזה. אם אתה מכפיל 23.23 במאה, ורק אח"כ עושה המרה ל-int, אז החלק העשרוני הוא אפס, ולכאורה שום דבר לא אמור ללכת לאיבוד. לכן זה לא מסביר.
 

dogood

New member
למי שמחפש את התשובה למה זה ככה?

מספר ב FLOAT מורכב ממנטיסה ?! מספר המופיע כ 23.23 הוא למעשה 23.229999 כשאתה מכפיל ב100 אתה מקבל 2322
 

voguemaster

New member
ולמה לא 23.230000001 ??

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

נתן.ל

New member
../images/Emo51.gif לכולכם ...

אבל אם כל ההסברים האלה והתקנים האלה ... איך אתם מסבירים שמה שיאיר הציע פועל מצויין ?
 

yair24

Member
מה שניסו להסביר לך פה...

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

yair24

Member
מה שעשיתי פה היה:

עקפתי את הבעיה שנוצרת כשאתה מכפיל שני מספרי FLOAT ואת התוצאה מכניס ישר לINT (כי אז יש איבוד מידע) והכנסתי את התוצאה לתוך FLOAT, עכשיו בגלל שהתוצאה היתה שלמה אז אילוץ לINT נתן תוצאה שלמה ונכונה. יאיר
 
למעלה