انجمن کاربران لینوکس ایران - تکنوتاکس سابق

نسخه ي کامل: ساختار ذخیرهء اعداد اعشاری و نمود آن در سطح برنامه نویسی
شما در حال مشاهده نسخه ي متني اين صفحه هستيد. مشاهده نسخه کامل تر با قالب بندي صحيح
رایانه ها با اعداد با نقطهء اعشاری یک مشکل عام دارند، چون رایانه ها فقط میتوانند مقادیر متناهی با اندازهء ثابت را ذخیره کنند. اعداد اعشاری میتوانند هر طولی داشته باشند، شامل طول نامتناهی (دربارهء یک اعشار تکرارشونده، همچون نتیجهء ۱ تقسیم بر ۳ فکر کنید).

روشی که یک رایانه اعداد اعشاری را مدیریت میکند اینست که آنها را با یک دقت ثابت (تعداد بیتهای معنادار) ذخیره میکند. یک رایانه اعداد اعشاری را در دو بخش ذخیره میکند - «نما» و «مانتیس». مانتیس ارقامی را که عملا مورد استفاده قرار خواهند گرفت دربر دارد، و نما بزرگی عدد است. برای مثال، ۱۲۳۴۵٫۲ بصورت ۱٫۲۳۴۵ ضربدر ۱۰ به توان ۴ ذخیره میشود. مانتیس ۱٫۲۳۴۵ و نما ۴ است. تمام اعداد بصورت x.xxxxx * 10^xxxx ذخیره میشوند. عدد ۱ بصورت ۱٫۰۰۰۰۰ ضربدر ۱۰ بتوان صفر ذخیره میشود.
اکنون، مانتیس و نما فقط آنقدر طولانی هستند که منجر به بعضی مسائل جالب میشود. برای مثال، وقتی یک رایانه یک عدد صحیح را ذخیره میکند، اگر شما عدد ۱ را به آن بیافزایید، عدد نتیجه شده یکی بزرگتر میشود. این لزوما برای اعداد اعشاری اتفاق نمی افتد. اگر عدد بقدر کافی بزرگ باشد، همچون ۵٫۲۳۴ ضربدر ۱۰ به توان ۵۰۰۰، اضافه کردن ۱ بدان حتی ممکن است در مانتیس ثبت نشود (بیاد بیاورید، هر دو بخش فقط آنقدر طولانی هستند). این چند چیز را تحت تاثیر قرار میدهد، بخصوص ترتیب عملیات ها را. بگذارید بگوییم که من ۱ را به ۵٫۲۳۴ ضربدر ۱۰ بتوان ۵۰۰۰ چند میلیارد بار یا چند هزار میلیارد بار اضافه کنم. حدس بزنید چه میشود - عدد به کلی تغییری نمی کند. گرچه، اگر من یک را به تعداد کافی به خودش اضافه کنم، و سپس آنرا به عدد اصلی اضافه کنم، آن میتواند تغییری ایجاد کند.

========

منبع:
[ltr]
Programming from the Ground Up
by Jonathan Bartlett
Edited by Dominick Bruno, Jr.
Copyright © 2003 by Jonathan Bartlett
<!-- m --><a class="postlink" href="http://download.savannah.gnu.org/releases/pgubook/ProgrammingGroundUp-1-0-booksize.pdf">http://download.savannah.gnu.org/releas ... oksize.pdf</a><!-- m -->
[/ltr]

کسی اگر خاصیت و مثال دیگه ای هم میدونه بگه.
بنده در گذشته به چند باگ یا مشکل و رفتار گیج کننده در این ارتباط در برنامه هام برخورد کرده بودم و بنظرم موردهای دیگری از رفتارهای غیرمنتظره و غیرقابل توجیه (درصورت عدم اطلاع از این قضایا) در ارتباط با عملیات روی اعداد اعشاری رو دیده یا خونده بودم.

مهمان

خب کلیتی از یکسری مسایل دیگه که در ارتباط با اعداد اعشاری ممیز شناور (Floating point) ممکنه رخ بدن:
کد :
(a + b) ×c ?= a×c + b×c

(a + b) + c ?= a + (b + c)
منظور از ?= در عبارات بالا این هست که در مواردی دو طرف میتونن مساوی نباشن! درحالیکه از نظر ریاضی دقیقا یکسان هستن و به گمانم هیچ برنامه نویسی هم انتظار نداره که مساوی نباشن. اما این امکان وجود داره. اینکه رخ میده یا نه، ظاهرا بستگی به عوامل مختلفی داره که شاید جز آزمون و احتیاط و زیرنظر گرفتن دقیق راه ساده ای برای جلوگیری از خطاهای پیش آمده در برنامه از این طریق نباشه؛ مگر اینکه دقیقا خصوصیات سخت افزار و نرم افزار (شامل کامپایلر) و مشخصات و پارامترهای عملیات انجام شده رو بدونید و با ساختار اعداد ممیز شناور و آنالیز ریاضی لازمه کاملا آشنا باشید.

مورد بعدی اینه که تفریق اعدادی که خیلی نزدیک بهم هستن میتونه به کاهش شدید دقت عملیات منجر بشه (یعنی خطا از تقریب طبیعی اعداد ممیز شناور هم خیلی فراتر بره). به این رخداد Cancellation گفته میشه.

عملیات مقایسه برای تساوی بین نتایج حاصل از دو عملیات ممیز شناور که از نظر ریاضی معادل هستن ممکنه خطا کنه، چون بسته به نوع عملیات و ترتیب عملوندها و پارامترهای دیگر، نتیجه براحتی میتونه تفاوت داشته باشه (توجه کنید که حتی یک اختلاف جزیی در عملیات مقایسه برای تساوی منجر به تفاوت نتیجهء مقایسه میشه).

باید متوجه عملیات Type cast هم بود چون در بعضی موارد ممکنه نتایج غیرمعمول بده. بعنوان مثال:
کد :
printf("%d\n", (int)((float)63.0/(float)9.0));// result: 7
printf("%d\n", (int)((float)0.63/(float)0.09));// result: 6
این خطا به این علت پیش میاد که عملیات Type cast معمولا گرد نمیکنه و بجاش بخش اعشاری رو کاملا نادیده میگیره. همچنین در کار با توابعی مثل Floor و ceil اینطور خطا میتونه پیش بیاد.

خب برای تعدادی از این محدودیت ها یا خطاها راهکارهای نرم افزاری خاصی ارایه شده. اما تقریبا هیچکدام کلی و صددرصد امن نیستن، ولی بهرحال میتونن پاسخگوی بعضی از نیازهای معمول باشن؛ بخصوص در برنامه هایی که نوع و محدودهء داده های اونها نسبتا محدود و معین و قابل پیش بینی هست. برای جستجو و مطالعهء این راهکارها به منبع ارایه شده برای این محتویات مراجعه کنید.

منبع: <!-- m --><a class="postlink" href="http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems">http://en.wikipedia.org/wiki/Floating_p ... y_problems</a><!-- m -->