الارتباك مع أرقام النقاط العائمة
-
27-09-2019 - |
سؤال
int main()
{
float x=3.4e2;
printf("%f",x);
return 0;
}
انتاج:
340.000000 // It's ok.
ولكن إذا اكتب x=3.1234e2
الإخراج هو 312.339996
و إذا x=3.12345678e2
الإخراج هو 312.345673
.
لماذا هذه المخرجات مثل هذه؟ أعتقد أنه إذا كتبت x=3.1234e2
يجب أن يكون الإخراج 312.340000
, ، لكن الإخراج الفعلي هو 312.339996
باستخدام برنامج التحويل البرمجي GCC.
المحلول
ليس كل الأرقام الكسرية لها مكافئ ثنائي دقيق بحيث يتم تقريبها إلى أقرب قيمة.
مثال مبسط ،
إذا كان لديك 3 بت للكسر ، فيمكنك الحصول على:
0
0.125
0.25
0.375
...
0.5 لديه تمثيل دقيق ، ولكن سيتم عرض 0.1 على أنها 0.125.
بالطبع الاختلافات الحقيقية أصغر بكثير.
نصائح أخرى
عادة ما يتم تمثيل أرقام النقطة العائمة ككسور ثنائية في قوة اثنين ، من أجل الكفاءة. هذا هو دقيق مثل التمثيل الأساسي 10 ، باستثناء أن هناك كسور عشرية لا يمكن تمثيلها بالضبط مثل الكسور الثنائية. إنهم ، بدلاً من ذلك ، ممثلون كتقريب.
علاوة على ذلك ، أ float
عادة ما يكون 32 بت 32 بت ، مما يعني أنه لا يحتوي على كل هذه الأرقام المهمة. يمكنك أن ترى في الأمثلة الخاصة بك أنها دقيقة لحوالي 8 أرقام مهمة.
ومع ذلك ، فأنت تقوم بطباعة الأرقام لتجاوز أهميتها قليلاً ، وبالتالي فأنت ترى الفرق. انظر الى خاصتك printf
تنسيق وثائق سلسلة لمعرفة كيفية طباعة عدد أقل من الأرقام.
قد تحتاج إلى تمثيل الأرقام العشرية بالضبط ؛ يحدث هذا غالبًا في الطلبات المالية. في هذه الحالة ، تحتاج إلى استخدام مكتبة خاصة لتمثيل الأرقام ، أو ببساطة حساب كل شيء على أنه أعداد صحيحة (مثل تمثيل مبالغ مثل السنتات بدلاً من الدولارات والكسور من الدولار).
المرجع القياسي هو ما يجب أن يعرفه كل عالم كمبيوتر عن الحساب العائم, ، ولكن يبدو أن ذلك سيكون متقدمًا جدًا بالنسبة لك. بدلاً من ذلك ، يمكنك Google Floating Pointates (وخاصة التنسيقات القياسية IEEE) أو البحث عنها على ويكيبيديا ، إذا كنت تريد التفاصيل.