PDA

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



elec60
سه شنبه 02 دی 1393, 19:18 عصر
سلام،

تو سی شارپ تایپ double مطابق استاندارد IEEE-754 پیاده سازی شده، پس فقط ۱۵ رقم اعشار دقت داره، به همین دلیل اگه عددی اعشاری با تایپ double بخواد ذخیره بشه به نوعی گردسازی انجام میشه.

حالا سوال من اینه: اگه تا ۱۵ رقم اعشار دقت داره پس چرا عدد یک صدم دقیق ذخیره نمیشه؟! برای مثال اگه حاصل ۴۵.۱۸ منهای ۴۵.۱۷ رو تو یه متغیر double ذخیره کنیم و تو پنجره local ویژوال استودیو مقادیر رو ببینیم این مقدار رو بجای یک صدم، ۰.۰۰۹۹۹۹۹۹۹۹۹۹۹۹۹۷۸۶۸ نشون میده؟!

چرا یک صدم داخل متغیر double نمیونه دقیق جا بگیره؟ مگه دقت این تایپ ۱۵ رقم اعشار نیست؟!

اگه تایپ رو به decimal تبدیل کنیم این مشکل حل میشه! البته باید جلوی اعداد M بزاریم تا کامپایلر خطا نگیره و ۴۵.۱۸ و ۴۵.۱۷ رو double در نظر نگیره.

اگه اشتباه نکنم دقت اعشار decimal برابر ۲۸ رقمه. خوب double هم ۱۵ رقمه و ۰.۰۱ رو باید بتونه دقیق ذخیره کنه!

eshaghrahimy
سه شنبه 02 دی 1393, 19:35 عصر
به این مقاله
http://www.dotnettips.info/post/1898/%D8%B1%D9%88%D8%B4-%D8%B5%D8%AD%DB%8C%D8%AD-%D9%85%D9%82%D8%A7%DB%8C%D8%B3%D9%87-%D8%AF%D9%88-%D8%B9%D8%AF%D8%AF-%D8%A7%D8%B9%D8%B4%D8%A7%D8%B1%DB%8C-%D8%A8%D8%A7-%D9%87%D9%85

elec60
سه شنبه 02 دی 1393, 19:46 عصر
به این مقاله
http://www.dotnettips.info/post/1898/%D8%B1%D9%88%D8%B4-%D8%B5%D8%AD%DB%8C%D8%AD-%D9%85%D9%82%D8%A7%DB%8C%D8%B3%D9%87-%D8%AF%D9%88-%D8%B9%D8%AF%D8%AF-%D8%A7%D8%B9%D8%B4%D8%A7%D8%B1%DB%8C-%D8%A8%D8%A7-%D9%87%D9%85

این مقاله از آقای وحید نصیری رو قبلا خوندم، ولی مشکلم حل نشده!
سوالم اینه که چرا ۰.۰۱ نمیتونه دقیق ذخیره بشه؟
آقای نصیری فقط گفتن عدد ۰.۰۱ نمیتونه دقیق ذخیره بشه ولی علت دقیقشو بیان نکردن

rahnema1
سه شنبه 02 دی 1393, 20:15 عصر
سلام
اینکه اشاره شده دقت تا 15 رقمه فقط به صورت کلی گفته حتی مثلا 45.18 دقیقا به این صورت ممکنه در کامپیوتر ذخیره نشه
مثلا float که 32 بیتی هست را در نظر بگیرید مطابق استاندارد ieee آخرین عدد که Inf هست
عدد یکی مانده به آخر به صورت دودویی در کامپیوتر به این صورت ذخیره میشه
01111111011111111111111111111111
که معادل اعشاری اون میشه
340282346638528859811704183484516925440

حالا عدد دو تا مانده به آخر به صورت دودویی میشه
01111111011111111111111111111110
معادل اعشاری:
340282326356119256160033759537265639424

حالا اختلاف این دو عدد برابره با :
20282409603651670423947251286016

یعنی در عدد های بزرگ رقمهای اعشار هم از بین میره و تقریب به کار می ره
توی این تاپیک چند منبع در زمینه نمایش اعداد اعشاری به صورت دودویی معرفی شده:
http://barnamenevis.org/showthread.php?470141

elec60
سه شنبه 02 دی 1393, 22:32 عصر
علتشو فهمیدم، آقای وحید نصیری علتشو تو سایتش نوشته بود! من ندیده بودم. آقای نصیری درک خیلی عمیقی از دات نت دارن و سایتشون خیلی پرباره.

نوع double به میزان ۶۴ بیت(۸ بایت) فضا میگیره، عددی مثل ۰.۰۱ اگر قرار باشه با استاندارد IEEE نمایش داده بشه باید قسمت صحیحش صفر بشه که راحت میشه این قسمت رو صفر کرد(همه بیتهای قسمت صحیح برابر صفر) اما قسمت اعشاریش باید با استفاده از توانهای منفی عدد ۲(مبنا) ساخته بشه که با توجه به محدود بودن تعداد بیتها نمیشه دقیق به ۰.۰۱ رسید.

حالا دقیقا افتاد که چه خبره:)

نوع decimal هم مبناش بجای ۲ عدد ۱۰ هست و به همین دلیل محاسبات دهدهی راحت تر دو دقیق تره، برای قسمت اعشاری مثال عدد ۰.۰۱ رو میشه به صورت 0.01 (منظور باینری قسمت اعشاری هست) نمایش داد که میشه ۱۰ به توان ۲- ضربدر ۱ به اضافه ۱۰ به توان ۱- ضربدر ۰

نوع double توسط CPU به طور مستقیم پشتیبانی میشه(مبناش ۲ هست) اما نوع decimal خیر و محاسبات بیشتری برای پیاده سازی میخواد و به همین دلیل تا ۱۰ برابر کندتره(به نقل از کتاب جوزف البهاری)