العمليات من النوع المزدوج في C


يرجى شرح كيف يعمل؟ البرنامج يعطيني النتيجة الصحيحة فقط عندما أقوم بإضافة أعداد صحيحة، ولكن في مهمتي أفضل استخدام النوع double.

خيار العمل:
`

سي ++
for (int i = -10000; i < 10000; i++) {
    formula = s1 / (v1 + k) + s2;
    if (formula == 0) {
        break;
}
    k += 1;
}

النتيجة:3.000000
`

لا يعمل بشكل صحيح:
`

سي ++
for (int i = -10000; i < 10000; i++) {
    formula = s1 / (v1 + k) + s2;
    if (formula == 0) {
        break;
}
    k += 0.00001;
}

النتيجة:0.200000
`

ما حاولت:

أحتاج في برنامجي إلى نتيجة أكثر دقة حتى لا أتمكن من استخدام النوع int.

الحل 1

الخطوة الأولى هي التأكد من المتغيرات formula, s1, s2, v1، و k كلها من النوع المزدوج. أنت في الواقع لا تحتاج إلى أن تكون جميعها مزدوجة ولكنك تريد التأكد من النتيجة (formula) هو مزدوج والقسمة يجب يتم مع الزوجي. النتيجة الصحيحة ستكون مضمونة تقريبًا لإعطاء نتائج خاطئة.

الخطوة الثانية هي الحذر من المقارنات المتساوية مع القيم المزدوجة، أي اختبار إذا formula هو صفر. الأسلوب المعتاد لذلك هو تحديد قيمة إبسيلون التي تعني “قريب بدرجة كافية” ومقارنتها بذلك. هنا مثال :

سي ++
const double epsilon = 1.0E-9;

// do calculations here

double delta = fabs( formula );
if( delta < epsilon )
    break;

سيؤدي هذا إلى الخروج من الحلقة إذا formula يقع في النطاق بين -1E-9 و+1E-9. يمكنك استخدام 1.0E-6 أو قيم أخرى لـ epsilon طالما أنها ضمن التسامح الحسابي المطلوب.

الحل 2

هناك العديد من الأشياء التي يجب ملاحظتها هنا. يبدو أن المتغير k فقط هو الذي يتغير مع كل حلقة.

ج
for (int i = -10000; i < 10000; i++) {
  formula = s1 / (v1 + k) + s2;
  if (formula == 0) {
	break;
  }
  k += 0.00001;
}

لسوء الحظ، لا يمكن تخزين القيمة k += 0.00001 تمامًا على شكل عدد عشري (أو مزدوج)، لذلك يستخدم المترجم عادةً القيمة الأقرب. إذا قمت الآن بجمع هذه الأرقام المزدوجة غير المتطابقة تمامًا، فسيزداد الخطأ في المجموع مع كل حلقة.

هناك الآن عدة طرق لحل المشكلة.
1. بدلاً من الإضافة المستمرة مرة أخرى، من الأفضل الضرب مرة واحدة في مؤشر الشريحة، مما يزيد من الدقة بشكل كبير.
2. بدلاً من مقارنة عائمتين مباشرة مع بعضهما البعض، سيكون من الأفضل التحقق من الفرق، حيث لا يصبح الفرق في كثير من الأحيان 0، ولكن يجب أن يقل عن قيمة محددة.

إن استخدام double بدلاً من float للحصول على دقة أفضل لن يؤدي إلا إلى تغيير المشكلة وليس حلها.

コメント

タイトルとURLをコピーしました