دقة الإخراج المزدوج الطويل غير صحيحة.ما قد يكون الخطأ؟

StackOverflow https://stackoverflow.com/questions/684112

سؤال

انا املك long double الثابت الذي أقوم بإعداده إما على أنه ثابت أو غير ثابت.إنها أطول (40 رقمًا) من دقة أ long double في محطة العمل الاختبارية الخاصة بي (19 رقمًا).

عندما أقوم بطباعته، لم يعد يتم عرضه بدقة 19 رقمًا، ولكن بدقة 16.

هذا هو الكود الذي أقوم باختباره:

#include <iostream>
#include <iomanip>
#include <limits>
#include <cstdio>

int main ()
{
    const long double constLog2 = 0.6931471805599453094172321214581765680755;
    long double log2 = 0.6931471805599453094172321214581765680755;    

    std::cout << std::numeric_limits<long double>::digits10 + 1 << std::endl;
    std::cout << "const via cout: " << std::setprecision(19) << constLog2 << std::endl;
    std::cout << "non-const via cout: " << std::setprecision(19) << log2 << std::endl;
    std::fprintf(stdout, "const via printf: %.19Lf\n", constLog2);
    std::fprintf(stdout, "non-const via printf: %.19Lf\n", log2);

    return 0;
}

تجميع:

$ g++ -Wall precisionTest.cpp

انتاج:

$ ./a.out
19
const via cout: 0.6931471805599452862
non-const via cout: 0.6931471805599452862
const via printf: 0.6931471805599452862
non-const via printf: 0.6931471805599452862

أتوقع 0.6931471805599453094 ولكن بدلا من ذلك الحصول على 0.6931471805599452862.

هل هناك سبب لتقليص أرقام الدقة المكونة من 19 رقمًا إلى 16 رقمًا؟

هنا بيئتي:

$ gcc --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)

أرى نفس المشكلة مع الإصدارات الأخرى من دول مجلس التعاون الخليجي، على سبيل المثال:

$ gcc --version
g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)

يمكنني البحث في NTL أو المكتبات الأخرى ولكن لدي فضول لمعرفة سبب ذلك.شكرا لبصيرتك.

هل كانت مفيدة؟

المحلول

وأحصل على هذا الإخراج:

19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094

ولكن أنا باستخدام الحرفية مزدوجة طويلة بدلا من الحرفية مزدوجة:

const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;    

نصائح أخرى

هناك بعض المشكلات الدقيقة المتعلقة بمنصات الأجهزة وخيارات الترجمة التي قد تكون ذات أهمية:

تم تحديد خيارات `-m' هذه لعائلة أجهزة الكمبيوتر i386 وx86-64:

-m96bit-طويل-مزدوج

-m128bit-طويلة-مزدوجة

تتحكم هذه المفاتيح في حجم النوع المزدوج الطويل.تحدد الواجهة الثنائية للتطبيق I386 الحجم ليكون 96 بت ، لذلك -M96bit-Long-Double هو الافتراضي في وضع 32 بت.تفضل البنى الحديثة (Pentium و Gewer) محاذاة مضاعفة طويلة مع حدود 8 أو 16 بايت.في المصفوفات أو الهياكل التي تتوافق مع ABI ، لن يكون هذا ممكنًا.لذا ، فإن تحديد -2128 بت من الطول سوف يتوافق مع حدود 16 بايت عن طريق حشوة مضاعفة طويلة مع صفر إضافي 32 بت.

في برنامج التحويل البرمجي x86-64 ، فإن -M128bit-long-double هو الخيار الافتراضي حيث يحدد ABI أنه سيتم محاذاة مزدوجة طويلة على حدود 16 بايت.

لاحظ أن أيًا من هذه الخيارات لا يمكّن أي دقة إضافية على معيار X87 البالغ 80 بت لمضاعفة طويلة.

تحذير:إذا قمت بتجاوز القيمة الافتراضية لـ ABI المستهدف ، فإن الهياكل والصفائف التي تحتوي على متغيرات مزدوجة طويلة ستغير حجمها بالإضافة إلى تعديل اتفاقية استدعاء الوظائف لأخذ الوظيفة المزدوجة الطويلة.وبالتالي لن تكون متوافقة مع المصفوفات أو الهياكل في الكود التي تم تجميعها بدون هذا التبديل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top