الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

هل تستطيع حل سؤال الـ Template هذا

مغلقمُجاب
بدأه C++er في 22 أغسطس 2011 · 1 رد · 593 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

العمليات على مستوى البت ممتعه جدا و لها تطبيقات لا حصر لها، يمكنك مراجعة هذه الصفحه لمزيد من التطبيقات.

المشكله التاليه واجهتنى اثناء تضمين النوع float_t و قمت بحلها و لكنى اطمح فى ايجاد حلول افضل.

النوع float كما يتم تضمينه تبعا لـ IEEE يأخذ الشكل التالي:

float
  sign = 1-bit
  exp  = 8-bits
  frac = 23-bits

double
  sign = 1-bit
  exp  = 11-bits
  frac = 52-bits

و بشكل عام فإن المعادله للحصول على عدد البتات لكل جزء هى كالتالي: (بإفتراض ان المساحه الكليه بالبت و ممثله بقيمة المتغير n):

type size = n-bits

  sign = 1-bit
  exp  = floor(4 * log2(n)) - 13
  frac = n - (sign + exp)

مثلا للحصول على عدد البتات لنوع float64 - تم ذكره بالأعلي - تكون النتائج كالتالي:

type size = 64-bits

  sign = 1
  exp  = floor(4 * log2(64)) - 13 = 24 - 13 = 11
  frac = 64 - (sign + exp) = 64 - (1 + 11) = 64 - 12 = 52

الأن نريد تضمين الفئه float_t كـ template class و شكلها المفترض ان يكون كالتالي:

template<typename t, unsigned size>
struct float_t
{
    union
    {
        t all[ size/(CHAR_BIT*sizeof(t)) ];

        struct
        {
            t sign:?;
            t exp:?;
        } parts;

    } value;
};

كما ترى قمت بعمل union ليحتوى على الـ sign و الأس و لكنى عدد البتات التى سيتم تحديدها لهم المفترض ان تتناسب مع المعادله التى تم وضعها بالأعلي.

لذا السؤال الأن كيف يتم تحديد عدد البتات لعناصر الـ union وقت الترجمه و ايضا كيف تتأكد من أن قيمة المتغير size هو من مضاعفات الرقم 2؟

ملاحظه: log2 لرقم صحيح هو عدد البتات المستهكله ما عدا اخر بت، بمعنى ان الرقم 5 يماثل 101 بالنظام الثنائي و بالتالي log2(5) = 2، راجع الربط بالأعلي لمثال تطبيقي.

**********************************

سؤال أخر: كيف تقوم بحساب log10 لرقم صحيح وقت الترجمه؟

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 22 أغسطس 2011 في 23:21

مدونتي: C++ Tips and Tricks

#2 أفضل إجابة

الحل الخاص بي ينقسم إلى جزئين، الأول خاص بالحصول على اللوغارتم للأساس 2 وقت الترجمه و الكود الخاص بها كالتالي:

template<unsigned value>
struct Log2
{
    static const unsigned Value = value&0? 0: (1 + Log2<(value>>1)>::Value);
};

template<>
struct Log2<1>
{
    static const unsigned Value = 0;
};

مع C++0x يمكن عدم استخدام الـ templates و استخدام constexpr بدلا منها:

constexpr unsigned Log2(unsigned value)
{
   unsigned r = 0;
   while(vlaue>>=1) r++;
   return r;
}

كلا الكودين لهما نفس النتيجه و لكن الأخير لن يعمل إلا مترجم يدعم constexpr و هم قليل.

الجزء الثاني من الحل يختص بالنوع float_t:

template<int size>
struct global_float_t
{
    static const unsigned sign_size = (size>=16) && !(size & (size - 1));
    static const unsigned exponent_size = (4*Log2<size>::Value) - 13;
    static const unsigned mantissa_size = size - (exponent_size + sign_size);
};

template<typename t, unsigned size>
struct float_t
{
    union
    {
        t all[ size/(CHAR_BIT*sizeof(t)) ];

        struct
        {
            t exp  : global_float_t<size>::exponent_size;
            t sign : global_float_t<size>::sign_size;
        } parts;
    } value;
};

النوع global_float_t يحتوى مبدئيا على المساحات الخاصه بكل جزء، الجزء الذى قد يسترعي انتباهك هو كود الثابت sign_size حيث من المعادلات السابقه يتبين لنا انه ذو حجم ثابت و هو 1-بت و مع ذلك فقد تم كتابة كود له. هذا الكود ينقسم إلى جزئين الأول يتحقق من ان الـ size ليست أقل من 16-بت فإن كان اقل فإن القيمه ستكون صفر و بالتالي مساحة المتغير sign داخل النوع float_t ستصبح صفر و هو ما لا تقبله اللغه و بالتالي اضمن بهذا الجزء من الكود ان المساحة ستكون اكبر من او تساوى 16-بت. الجزء الثاني من الكود يتأكد من ان المساحه المدخله هى من مضاعفات الرقم 2 فإن كان غير ذلك سيحدث الخطأ المذكور منذ قليل.

الثابت exponent_size يستخدم Log2 للحصول على قيمة مساحة الأس.

******************************

للحصول على Log10 لأرقم صحيح وقت الترجمه استخدم الكود التالي:

template<int value>
struct Log10Healper
{
    static const unsigned Value = value<0? 0: (10 * Log10Healper<value - 1>::Value);
};

template<>
struct Log10Healper<1>
{
    static const unsigned Value = 10;
};

template<>
struct Log10Healper<0>
{
    static const unsigned Value = 0;
};

template<unsigned value>
struct Log10
{
    static const unsigned Value = unsigned((Log2<value>::Value + 1) * 0.301f) - (value < Log10Healper<unsigned((Log2<value>::Value + 1) * 0.301f)>::Value);
};

التحسينات و التعديلات مرحب بها.

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 23 أغسطس 2011 في 08:04

مدونتي: C++ Tips and Tricks

هذا الموضوع مغلق.

مواضيع مشابهة