ورود

View Full Version : سوال: مقایسه اعداد اعشاری



***BiDaK***
پنج شنبه 15 تیر 1391, 15:32 عصر
سلام.یه مشکلی که توو کامپایلر ویژوال هست مثلا یه مقدار 0.99999999 به متغیر از نوع اعضاری میدیم تبدیل میشه به عدد یک و توو خروجی 1 رو چاپ میکنه و توو مقایسه ها هم اشتباه میشه..
حالا میخوام بدونم راهکارش چیه؟
یا مثلا کدیرو میدیم تو کامپایلر:
if (a==1)
cout << "yek";
یــــــا
if (a<1)
cout << "*******";
یــــــا
if (a<b)
cout << "yes";
برای اینکه خطایی تو محاسباتش انجام نشه بهترین راه چیه؟ حالا حساب کنین این دستورا پشت سر هم توو else if بیاد بهترین کار چیه تا این مشکلات پیش نیاد و جواب درست رو بده؟؟؟؟؟:متفکر:

Ananas
پنج شنبه 15 تیر 1391, 16:14 عصر
سلام.
نوع float دقت اعشارش تا 7 رقم هست و خودشم متغیر 32 بیتی هست. از double که 64 بیتی هست و 16 رقم اعشار دقت داره و یا نوع long double که 80 بیتی هست و تا 18 رقم دقت اعشار داره استفاده کنید.

***BiDaK***
پنج شنبه 15 تیر 1391, 17:19 عصر
سلام.
نوع float دقت اعشارش تا 7 رقم هست و خودشم متغیر 32 بیتی هست. از double که 64 بیتی هست و 16 رقم اعشار دقت داره و یا نوع long double که 80 بیتی هست و تا 18 رقم دقت اعشار داره استفاده کنید.
ممنون.حرفای شما درسته..ولی با این وجود که این راه هس من راه دیگه ای هم که دیدم:
if (a-1<0.000000001)
یـــــا
if (fabs(a-1)<0.000000001)

حالا با توجه به اینکه می تونیم نوع متغیرامونو عوض کنیم پس چرا ازین راه استفاده میکنن مگه مقادیری هس که توو راه تغییر نوع متغیر جواب نده راهش؟؟؟؟یاکه کلا همون راه تغییر نوع متغیر کامله؟؟؟
بعد واسه اینکه توو خروجیمونم درست چاپش کنیم و گرد نکنه راهی هست؟؟؟
ممنون http://www.freesmile.ir/smiles/366219_4plnvbq.gif

the king
پنج شنبه 15 تیر 1391, 17:42 عصر
فرقی نمی کنه که نوع داده اعشاری با ممیز اعشاری ای که انتخاب می کنید چند بیتی است و چقدر دقت داره، به هر حال این
خاصیت ممیز شناور است که در محاسبات اش تخمینی عمل کنه. وقتی دقت بیتی بیشتر میشه میزان اختلاف کم میشه اما مشکل همچنان
پا برجا است، a با b برابر نیست، چه با دفت کم که 1.0001 با 0.9999 برابر نیست و چه با دقت بالا که 1.000000000000001 با 0.999999999999999 برابر نیست.
روال کلی اینه، هیچگاه یک مقداری که نوع داده اش اعشاری یه ممیز شناوره (مثل float و double) را با یک مقدار دیگر مستقیما مقایسه نکنید.
برایش مرز تخمین در نظر بگیرید، مثل همون دو مثالی که خودتون نوشتید که اگر فاصله دو مقدار کمتر از 0.0000001 بود ایندو مقدار را یکسان در نظر بگیره.
موقع نمایش خروجی میزان دقت اعشاری رو مشخص کنید، فرضا :

#include "iostream.h"
#include "iomanip.h"
#include "conio.h"

int main()
{
double n = 1.123456789;
cout << setprecision(7) << n << endl;
getch();
return 0;
}

Ananas
پنج شنبه 15 تیر 1391, 18:05 عصر
حالا با توجه به اینکه می تونیم نوع متغیرامونو عوض کنیم پس چرا ازین راه استفاده میکنن مگه مقادیری هس که توو راه تغییر نوع متغیر جواب نده راهش؟؟؟؟یاکه کلا همون راه تغییر نوع متغیر کامله؟؟؟
انواع double و long double باعث میشن دقت محاسباتتون زیاد بشه و تو محاسبات پی در پی خطای کمتری داشته باشن. ولی همون طور که دوستمون گفتن دقتشون محدوده و همون روش epsilon که به کار بردید برای مقایسه بهتره. البته برای مقایسه نه برای محاسبات. برای محاسبات باید با توجه به نیاز برنامه نوع رو انتخاب کنید. نوع float فضای کمتری رو اشغال میکنه (نصف double) و دقت کمتری داره در عوض نوع double و long double قادرند دامنه ی وسیع تری از اعداد رو پوشش بدن و دقت اعشار بالاتری هم دارن و از طرفی فضای بیشتری روی رم اشغال میکنن که تو آرایه ها اهمیتش معلوم میشه.
_________________________________
setprecision تو c++builder کار نمیکنه. چرا؟

***BiDaK***
پنج شنبه 15 تیر 1391, 18:42 عصر
فرقی نمی کنه که نوع داده اعشاری با ممیز اعشاری ای که انتخاب می کنید چند بیتی است و چقدر دقت داره، به هر حال این
خاصیت ممیز شناور است که در محاسبات اش تخمینی عمل کنه. وقتی دقت بیتی بیشتر میشه میزان اختلاف کم میشه اما مشکل همچنان
پا برجا است، a با b برابر نیست، چه با دفت کم که 1.0001 با 0.9999 برابر نیست و چه با دقت بالا که 1.000000000000001 با 0.999999999999999 برابر نیست.
روال کلی اینه، هیچگاه یک مقداری که نوع داده اش اعشاری یه ممیز شناوره (مثل float و double) را با یک مقدار دیگر مستقیما مقایسه نکنید.
برایش مرز تخمین در نظر بگیرید، مثل همون دو مثالی که خودتون نوشتید که اگر فاصله دو مقدار کمتر از 0.0000001 بود ایندو مقدار را یکسان در نظر بگیره.
موقع نمایش خروجی میزان دقت اعشاری رو مشخص کنید، فرضا :

#include "iostream.h"
#include "iomanip.h"
#include "conio.h"

int main()
{
double n = 1.123456789;
cout << setprecision(7) << n << endl;
getch();
return 0;
}

ممنونم.حالا مقدار تقریبمون 0.0000001 رو باید با چه دقتی بگیریم؟چون من داخل float با 7 رقم اعشار گرفتم 0.0000001 و دو مقدار 0.9999999 و 0.9999998 رو با هم مقایسه کردم که نتیجش شد برابر..بعد تعداد اعشار بیشتر کردم 0.000000001 که نتیجه ی درستیرو بهم داد...
سوال دیگمم اینه دو مقداری که دادم رو اینجوری گرد میکرد وقتی f10 میکردم..0.9999999 میذاشت 0.99999988 و مقدار 0.9999998 رو میذاشت 0.99999982 جریان خاصی داره؟؟؟؟
بازم ممنون.

Ananas
پنج شنبه 15 تیر 1391, 19:44 عصر
ممنونم.حالا مقدار تقریبمون 0.0000001 رو باید با چه دقتی بگیریم؟
بستگی به خودتون داره که از چقدر خطا صرف نظر کنید. ممکنه تو برنامه ی شما این عدد بتونه 0.01 هم باشه ولی در یک برنامه ی دیگه 0.0000000000001 . حد در ریاضی یعنی همین. هر چقدر که می تونی خطا داشته باشی (یعنی بزرگترین خطایی که می تونید نادیده بگیرید) یکم بزرگترش رو برای مقایسه انتخاب کن. البته دقت کن که تو نوع float دقت رو عددی کوچکتر از 0.0000001 نگیری چون تقریبا از هفت رقم به بعد دیگه تو نوع float ذخیره نمیشه و چیزی که بعد رقم هفتم نمایش میده معتبر نیست. مثلا 0.0000000000000001 برای نوع float درست جواب نمی ده. اگه همچین دقتی میخوای از نوع long double استفاده کن.