View Full Version : کار با اعداد اعشاری و یک اشکال عجیب
darehshoori
شنبه 09 تیر 1386, 17:07 عصر
با سلام.
من یه برنامه خیلی ساده نوشتم
#include<stdio.h>
#include<conio.h>
main(){
float a,b;
a=34.1256;
b=34.5432;
printf("%f",(b-a));
getch();
}
همانطور که می بینین یه برنامه فوق العاده پیش پا افتاده است.
جوابی که چاپ می شود 0.417603 است که دو رقم 03 اضافه هستند یا لااقل باید 0 باشند .
من با مقدار های دیگه و تعداد رقمهای دیگه هم تست کردم اما همیشه دو رقم آخر را یا اضافه می کنه یا یک جواب دیگه می دهد که دقیق نیست لطفا من را برای بدست اورد جواب دقیق که مثلا در مثال بالا 0.417600 است راهنمایی کنید.
با تشکر از راهنمایی شما.
someCoder
شنبه 09 تیر 1386, 17:20 عصر
http://barnamenevis.org/forum/showthread.php?p=359489#post359489
ماهیت اعداد اعشاری همینه که دقیق نیستند. بذار برات یه مثال بزنم تا بهتر متوجه بشی.
فرض کن میخوای عدد (1/3) رو در مبنای 3 نمایش بدی. جواب این میشه: 0.1
حالا همین عدد رو در مبنای 10 نمایش میدیم، میشه: 0.3333333333333333333333
خوب، پس میبینی که هر عدد اعشاری رو نمیشه تو هر مبنایی درست نشون داد. حالا عددی که تو مبنای 10 میشه نمایش داد، الزاما در مبنای 2 همون جوری ذخیره نمیشه و ممکنه گرد بشه.
راه حل این مشکل هم اینه که از float استفاده نکنی! اگر هم میخوای اعشاری باشه، خودت یه نوع جدید برای اعشار درست کن که توش دو تا int داشته باشه، یکی برای قسمت صحیح و یکی برای اعشاری و از اون استفاده کن.
emad_67
شنبه 09 تیر 1386, 18:35 عصر
این رقم های اضافه که در اعشار چاپ میکنه بر اساس چیه یهنی همین جوری چاپ میشه یا مورد دیگه ایی هست ضمنا من چند تا عدد رو امتحان کردم و و همشون درست جواب داد ولی رو این اعداد نمیدونم که چرا جواب دقیق نمیده میشه توضیح بیشتر بدید
darehshoori
شنبه 09 تیر 1386, 18:52 عصر
http://barnamenevis.org/forum/showthread.php?p=359489#post359489
ممنون از راهنماییتون.
پس با این صحبتها دیگه نمی شه از زبونهای برنامه نویسی برای محاسبات دقیق و اعضاری استفاده کرد مگر اینکه دو تا int تعریف کنیم درسته؟
یعنی هیچ راه حل دیگری وجود نداره؟
من حتی از Double هم استفاده کردم اما از اونجایی که double هم یه جور Float هست همین مشکل وجود داره.آیا تابعی وجود داره که مثلا 4 رقم اعشار یک عدد که دارای 6 رقم اعشار است رو نشون بده مثلا عدد 1.123456 را به عنوان ورودی بگیره و 1.1234 به عنوان خروجی تولید کنه؟
بازم ممنون.
someCoder
شنبه 09 تیر 1386, 19:10 عصر
این رقم های اضافه که در اعشار چاپ میکنه بر اساس چیه یهنی همین جوری چاپ میشه یا مورد دیگه ایی هست ضمنا من چند تا عدد رو امتحان کردم و و همشون درست جواب داد ولی رو این اعداد نمیدونم که چرا جواب دقیق نمیده میشه توضیح بیشتر بدید
گفتم که، وقتی اعداد اعشاری مبناشون عوض میشه، ممکنه تو مبنای مقصد نشه درست نشون داده بشن. این که چه عددی نشون داده بشه، بستگی به دقت (تعداد بیت عدد) داره. مثلا double دقیقتر از float میشه. البته همونطور که خودتم گفتی، این مساله همیشه پیش نمیاد و در مورد بعضی اعداد این مشکل پیش میاد. مثلا همین اعدادی که دوستمون در کدش استفاده کرده بود.
برای مثال بیشتر، مثلا این کد رو اجرا کن:
float i;
for(i=0;i<1.0;i+=0.01){
printf("%f\n", i);
}
قسمتی از نتایج کد رو کامپیوتر خودم این بود:
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999
میبینی که کلا همه چیز رو هواست!
برای فهم بیشتر، اون مثالی که برای مبنای 3 زدم رو بیشتر دقت کن.
someCoder
شنبه 09 تیر 1386, 19:20 عصر
ممنون از راهنماییتون.
پس با این صحبتها دیگه نمی شه از زبونهای برنامه نویسی برای محاسبات دقیق و اعضاری استفاده کرد مگر اینکه دو تا int تعریف کنیم درسته؟
یعنی هیچ راه حل دیگری وجود نداره؟
من حتی از Double هم استفاده کردم اما از اونجایی که double هم یه جور Float هست همین مشکل وجود داره.آیا تابعی وجود داره که مثلا 4 رقم اعشار یک عدد که دارای 6 رقم اعشار است رو نشون بده مثلا عدد 1.123456 را به عنوان ورودی بگیره و 1.1234 به عنوان خروجی تولید کنه؟
بازم ممنون.
درسته، محاسبات دقیق با اعداد اعشاری نمیشه کرد. چاره کار هم در نظر گرفتن یه حد آستانه برای خطاست. مثلا برای مقایسه دو تا float به جای تست معمولی تساوی از کد زیر استفاده میشه:
t = 0.0000001;
if(a-b<t){
//do something
}که تو این کد t همون حد آستانه خطاست.
برای نمایش دادن هم بستگی به روش چاپ کردن راهها مختلفی هست، مثلا برای printf اینجوری کار میکنن.
printf("%10.4f",(b-a));که این یعنی حداکثر عدد 10 کارکتر طولش میشه (با نقطه اعشار و قسمت اعشاری) و 4 رقم اعشار داره.
darehshoori
شنبه 09 تیر 1386, 19:38 عصر
درسته، محاسبات دقیق با اعداد اعشاری نمیشه کرد. چاره کار هم در نظر گرفتن یه حد آستانه برای خطاست. مثلا برای مقایسه دو تا float به جای تست معمولی تساوی از کد زیر استفاده میشه:
t = 0.0000001;
if(a-b<t){
//do something
}که تو این کد t همون حد آستانه خطاست.
برای نمایش دادن هم بستگی به روش چاپ کردن راهها مختلفی هست، مثلا برای printf اینجوری کار میکنن.
printf("%10.4f",(b-a));که این یعنی حداکثر عدد 10 کارکتر طولش میشه (با نقطه اعشار و قسمت اعشاری) و 4 رقم اعشار داره.
بازم ممنون از راهنماییتون.
شاید من منظورم و بد بیان کردم.
می خواهیم یه متغیر رو که دارای 6 رقم اعشار هست داخل یه متغیر دیگه بریزیم که 4 رقم اعشار بمونه.برای چاپ کردن اعشار حرف شما کاملا متین اما من می خوام یه متغیر اعشار رو داخل یه متغیر دیگه بریزم به طوری که متغیر دوم فقط چهار رقم اعشار از متغیر اول را داشته باشد.
someCoder
شنبه 09 تیر 1386, 19:44 عصر
من می خوام یه متغیر اعشار رو داخل یه متغیر دیگه بریزم به طوری که متغیر دوم فقط چهار رقم اعشار از متغیر اول را داشته باشد.نمیدونم راه مستقیم داره یا نه، اما چیزی که الان به فکر من میرسه اینه:
float a = 1.123456, b;
b = ((int)(a*10000))/10000.0;
printf("%f", b);
البته احتمالا راه بهتری هم باید باشه.
mansour_1363
یک شنبه 10 تیر 1386, 20:03 عصر
سلام برادر یا خواهر گرامی
من الان این مشکل شما را می خوانم نمی دانم تا حالا جواب آن را گرفته اید یا نه ؟ ولی من جواب آن را می دهم نمی دانم چقدر درست است ولی بر اساس تجربه ای که دارم می گویم
پاسخ : امکان اول : چون در جمع و تفریق اعداد اعشاری در این زبان به این صورت است که بعد از جمع یا هر نوع محاسبات دو عدد آخر گرد میشود و این جواب شما بدست می اید
mansour_1363
یک شنبه 10 تیر 1386, 20:03 عصر
سلام برادر یا خواهر گرامی
من الان این مشکل شما را می خوانم نمی دانم تا حالا جواب آن را گرفته اید یا نه ؟ ولی من جواب آن را می دهم نمی دانم چقدر درست است ولی بر اساس تجربه ای که دارم می گویم
پاسخ : امکان اول : چون در جمع و تفریق اعداد اعشاری در این زبان به این صورت است که بعد از جمع یا هر نوع محاسبات دو عدد آخر گرد میشود و این جواب شما بدست می اید
mansour_1363
یک شنبه 10 تیر 1386, 20:04 عصر
سلام برادر یا خواهر گرامی
من الان این مشکل شما را می خوانم نمی دانم تا حالا جواب آن را گرفته اید یا نه ؟ ولی من جواب آن را می دهم نمی دانم چقدر درست است ولی بر اساس تجربه ای که دارم می گویم
پاسخ : امکان اول : جمع و تفریق اعداد اعشاری در این زبان به این صورت است که بعد از جمع یا هر نوع محاسبات دو عدد آخر گرد میشود و این جواب شما بدست می اید
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.