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

تحويل العدد الست عشري إلى النظام العشري

بدأه مصطفى 36a2 في 27 يونيو 2012 · 12 رد · 6,167 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

ولكن كيف يمكننا أن نقوم بتحويل الناتج إلى النظام العشري بعد ذلك ؟؟

السؤال هو ... إذا كان لدينا رقم كبير كحد أقصى 1024 بايت

نريد تحويله للنظام العشري .. ونعرضه على الشاشة ...

وأهم المحددات لصحة الحل هو الوقت ... يجب ألا يتجاوز وقت حساب القيمة العشرية لمليون عدد مختلف ثانية واحدة ... (وليس وقت العرض)

وقت العرض 5 دقائق كحد أقصى ...

مثال :

الدخل:

0x12345678

الخرج:

305419896

حدود الوقت: ثانية وحدة من اجل حل 1000000 حالة ... ووقت العرض لا يتجاوز 5 دقائق لجميع الحالات ..

أؤكد على أن الحل الصحيح هو الذي يستطيع تحويل رقم من أمثال 0x123456789abacaaaa1242252262273585555564444444788888880000001112154649842

مليون مرة خلال ثانية واحدة وعرضه على الشاشة ...

أنتظر التفاعل .. لا أريد روابط لحلول .. أريد حلول جديدة من إبداعكم ...

والسلام عليكم ورحمة الله وبركاته ...

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 27 يونيو 2012 في 13:30

#2

يمكن الاستفادة من المعلومة التالية :

إن كل المعلومات على الشاشة عبارة عن محارف .. أي أن عملية العرض لا تتم إلا بعد تحويل العدد المطلوب إظهاره إلى محارف ..

ويمكنكم التّأكد من ذلك عبر تتبع عملية cout مثلا وذلك بضغط F11 بدلا من F5 عندما نريد تنفيذ البرنامج .. ( هذا في بيئة الVS6 ولا أعرف ما يقابلها في إصدارات أخرى )

إن لم يتم حل السؤال خلال ال72 ساعة القادمة فسأضع الحل الصحيح .. حتى لا تكون هذه المشاركة بلا فائدة

#3

السلام عليكم

أخي مصطفى, أرى أن كل مواضيعك أصحبت تصب في منحى واحد, و هو كيفية التعامل مع واجهة الــ console الساحرة :D

عموما, الفكرة الأصلية للموضوع تتعلق بإجراء العمليات الحسابية على الــ Big Integer, هذه الفكرة عبارة عن مشروع كبير شيئا ما .. قد يأخذ عدة أشهر لكي يرى نور الشمس, هناك محاولات سابقة لهذا المشروع مثل المكتبتين :

GMP (GNU Multiple Precision Arithmetic Library)

MIRACL (Multiprecision Integer and Rational Arithmetic C/C++ Library)

بالنسبة لقضية إظهار الأعداد على شاشة الــ console فسأتركها لبقية الإخوة لأنني لا أملك الآن شهية التفكير في الشاشة السوداء :sad:

أرجو لك التوفيق.

#4

:) بارك الله فيك أستاذي ... في الحقيقة في هذا الموضوع بالتحديد .. لا يهمني العرض بقدر ما يهمني الحساب الفعلي ..

فعملية تحويل العدد الست عشري إلى عشري ... بالفعل عملية صعبة ...

أستغرب حتى كيف يقوم بها الجهاز ...

....................................................................................

بغض النظر عن كيفية القيام بها للإعداد الكبيرة ...

كيف يقوم الحاسب نفسه بها حتى بالنسبة للأعداد الصغيرةhuh.gif

هل يُعقل انه يتبع الخوارزمية المعتادة مثلا لتحويل الرقم الثنائي 101011 يكون الجواب 1*2^0 + 1*2^1 + 0*2^2 + 1*2^3 + 0*2^4 + 1*2^5

بالنسبة لعدد 4 بايت من نوع integer ...

في الحقيقة هذا السؤال يحيرني ...

يمكنني القيام بذلك ولكن ماذا يفعل الجهاز ... ؟؟؟

سأقرأ الروابط التي وضعتها ...

ولكن هل يمكنك أن تجيبني على سؤالي ؟...

#5
اقتباس
كيف يقوم الحاسب نفسه بها حتى بالنسبة للأعداد الصغيرة ؟

أعتقد أن هذا السؤال يحتاج إلى معرفة جيدة بالأسمبلي و كيفية تحويل الكود إلى لغة يفهمها الجهاز و كيفية التنفيذ !

عموما, لستُ الأقدر على أجابة هذا النوع من الأسلئة و لكن سأعطيك "شبه إجابة" ريثما يأتي أحد الأعضاء ليشفي لك غليلك :D

.. يقوم المترجم بتحويل كود السي++ إلى لغة منخفضة المستوى (قد تشبه لغة الأسمبلى) تسمى Intermediate Representation, أعتقد أنه في هذه المرحلة سيكون تنفيذ الأوامر أسرع من ما كان عليه نظرا لقرب اللغة من لغة الآلة, بالإضافة إلى بعض التحسينات التي قد تطرأ على الكود نتيجة الــ Optimization.

بالتوفيق.

#6
مصطفى 36a2 كتب:

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

ولكن كيف يمكننا أن نقوم بتحويل الناتج إلى النظام العشري بعد ذلك ؟؟ السؤال هو ... إذا كان لدينا رقم كبير كحد أقصى 1024 بايت نريد تحويله للنظام العشري .. ونعرضه على الشاشة ...

وأهم المحددات لصحة الحل هو الوقت ... يجب ألا يتجاوز وقت حساب القيمة العشرية لمليون عدد مختلف ثانية واحدة ... (وليس وقت العرض)

وقت العرض 5 دقائق كحد أقصى ...

مثال الدخل: 0x12345678

الخرج: 305419896

حدود الوقت: ثانية وحدة من اجل حل 1000000 حالة ... ووقت العرض لا يتجاوز 5 دقائق لجميع الحالات ..

أؤكد على أن الحل الصحيح هو الذي يستطيع تحويل رقم من أمثال 0x123456789abacaaaa1242252262273585555564444444788888880000001112154649842

مليون مرة خلال ثانية واحدة وعرضه على الشاشة ... نتظر التفاعل .. لا أريد روابط لحلول .. أريد حلول جديدة من إبداعكم ...

والسلام عليكم ورحمة الله وبركاته ...

رائع سؤالك ...

لكن من اين لى بنوع البيانات الذى تريد تحويلة؟ هل يمكنك ادراج فئة نوع البيانات هذا هنا حتى نتمكن اجراء العمليات علية؟ أم علينا اختراع نوع البيانات ثم تطبيق خوارزمية التحويل ...

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

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#7
اقتباس
علينا اختراع نوع البيانات

لا أخي سيكون هذا إجحافا وعلي وضع 1000 نقطة لذلك ... وليس معي هذا المبلغ laugh.gif

يمكنك عمل برنامج بسيط يستقبل عدد ست عشري كمصفوفة محارف

ويعطي في خرجه العدد العشري المكافئ للعدد الست عشري المدخل

مثلاً:

الدخل : 0x123

الخرج : 291

فقط...ويمكن تطبيق ذلك من أجل رقم ست عشري من ألف منزلة مثلاً ... هل هناك سؤال آخر أخي ؟

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 27 يونيو 2012 في 17:40

#8
اقتباس
ليست المشكلة في السرعة بل في الخوارزمية المتبعة !!

ألا توافقني بأن الفكرة تستحق التفكير؟ :)

بلي :), الفكرة تستحق تحريك الجمجمة .. و تحتاج إلى نصف كيلو من الأسمبلي :D

اقتباس
مثلاً:

الدخل : 0x123

الخرج : 291

فقط...ويمكن تطبيق ذلك من أجل رقم ست عشري من ألف منزلة مثلاً ...

إذا كنت تتحدث عن الطريقة التقليدية لتحويل الــ hex إلى decimal فأعتقد أن هذا ما تريده :

#include<iostream>
#include<cstring>
using namespace std;

int power (int x , int y)
{
    int p=1 ;

    for (int i=0 ; i<y ; i++)
        p *= x ;

     return p;
}

int hexToDecimal    (char hex[])
{
     int tmp = 0 ;
     int sum = 0 ;
     int  hexNum[]  = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
     char hexChar[] = {'0','1','2','3','4','5','6','7','8','9',
                       'A','B','C','D','E','F'};

     for (int i=0 , j=strlen(hex)-1 ; i<strlen(hex) ; i++ )
     {
         for (int k=0 ; k<16 ; k++)
         {
             if (hex == hexChar[k])
             {
                tmp = hexNum[k] ;
                break;
             }
         }

         tmp = tmp * power(16,j--);
         sum += tmp ;
     }
     return sum ;
}

int main(){
    char hex[32] ;
    cout << "Enter The  hex   Number : " ;
    cin >> hex ;
    cout <<endl<< "In Decimal  :  " ;
    cout << hexToDecimal(hex)<<endl;
    return 0;
}

مثال على تنفيذ الكود :

post-219439-095417500 1340810872_thumb.p

أما إن كنا نتحدث عن استخدام طرق متقدمة للتحويل فيمكننا البحث عن الطريقة المُتبعة في الخرج std::hex بالنسبة لسي++ أو العلامة %x في لغة السي.

بالتوفيق.

المرفقات
test.png
1
#9

نعم أخي ليس أكثر من ذلك ولا تنسى أنه يجب أن يكون قادرا على تحويل رقم من منازل كثيرة ...

أما بالنسبة ل

اقتباس

أما إن كنا نتحدث عن استخدام طرق متقدمة للتحويل فيمكننا البحث عن الطريقة المُتبعة في الخرج std::hex

في الحقيقة أريد معرفة الطريقة المتبعة لstd::dec لأنه في العد الست عشري كل منزلة مستقلة عن المنزلة التالية ...

ويمكننا تخزين الرقم في مصفوفة ثم عرض العناصر كل عنصر لا يؤثر على الآخر ...

عند التحويل للعد العشري فال 15*16+ 5*256+2*66536 تثير الاشمئزاز كعملية معقدة وطويلة ... وكل منزلة نحسب قيمتها العشرية ستغير المنازل التي قبلها ...wacko.gif

أنا أعرف كيف أقوم بتحويل الرقم على الورق وبالطبع يمكنني كتابة كود للتحويل في المنازل الصغيرة ... ولكن كل ما كبر الرقم كلما تعقدت العملية بشكل مزعج..

شكراً لك على التفكير +1 laugh.gif

#10
اقتباس
شكراً لك على التفكير +1 :lol:

أين هي +1, لم أرها :P

اقتباس
في الحقيقة أريد معرفة الطريقة المتبعة لstd::dec

أنا من سألتُ أولا :D

اقتباس
ولكن كل ما كبر الرقم كلما تعقدت العملية بشكل مزعج..

عدنا للمربع الأول :)

الحل هنا يكمن في التعامل مع الـ Big Integer. لأنه يجب تخزين الناتج في متغير من نوع BigInteger.

الــ long و long long و حتى double long لا تنفع في هذه الحالة !

عموما, سأعود إلى عملي, حتى لا يغضب علي مشرفوا القسم ... فاليوم يومي في الفهرسة :D

بالتوفيق.

#11
اقتباس
لدي سؤال .. على حد علمي long مثل int تحجز 4بايت .. وسؤالي لماذا لا تعمل long long عندي .. علما أنني أستخدم VS6

أنا أستعمل عوضا عنهاint64__ وأقوم بتحميل زائد للعملية << لأتمكن من الإخراج ..

سبق و أن تم نقاش قضية "أحجام البيانات في السي/السس++", إليك خلاصة النقاش :

• المساحة التي يمثلها int في الذاكرة تتناسب مع الحاسب الذي تعمل عليه, فإذا كنت تعمل على جهاز 16 بت (مثل الدوس) فستكون مساحة int تساوي 2 بايت و إذا كنت تعمل على جهاز 32 بت (مثل ويندوز 2000) فستجد أن مساحة int هي 4 بايت أما إذا كنت تعمل على جهاز 64 بت (مثل ويندوز 7-x64) فستجد أن مساحة int تساوي 8 بايت.

• عندما تستخدم int فإن المترجم سيعتبره short أو long أو long long و ذلك حسب إعدادات المترجم الافتراضية.

• نختزل الملاحظتين السابقتين في الملاحظة التالية:

إذا كان لدينا جهاز عليه نظام تشغيل من نوع 32 بت فإن int بشكل افتراضي سيحجز مساحة 4 بايت, بعدها اللغة تركت لصانع المترجم الحرية في تحديد مساحة int فيمكنه تركها على الحالة الافتراضية أو تغييرها بما يتراءى لتصميمه, على سبيل المثال فإن المترجم (أو بيئة التطوير) Borland C++ v 4.5 يعتبر أن حجم int هو 2 بايت (مثل short ) أما Dev فيعتبر أن حجم int يساوي4 بايت (مثل long).

• كما رأينا بالأعلى فإن النوع int مساحته متغيرة, لنفترض انك تريد استخدام متغير رقمي صحيح بمساحة 4 بايت, إذا عمل برنامجك على نظام تشغيل 16 بت و أنت تستخدم int فسيكون مساحته 2 بايت و هذا قد يجعل برنامجك يفشل في تطبيق ما يريد !,فهو يتوقع أن حجم int هو 4 بايت و قد ظهر أن مساحته هي 2 بايت فما الحل؟

الحل هنا يكمن في استخدام طريقه تسمح لك بتحديد المساحة التي يستهلكها int مـن الذاكرة أو بمعنى أدق مدى الأرقام الذي يمكن تمثيله بـ int و ذلك سواء كنت تعمـل على نظام تشغيل 16بت أو 32 بت أو 64 بت أو غيرهم حيث ستكون المساحة التي يستخدمها برنامجك واحدة في كل الأحوال.

هذه الطريقة تتم باستخدام ما يسمى بـ Length Modifier أو "محددات المساحة" إن صح التعبير !.

• الـ Length Modifier هي كلمات محجوزة مسبقا, باستخدامها مع int تجعل مدى الأرقام الذي يمكن تمثيله به ثابت و لا يتغير من نظام تشغيل لآخر أو بمعنى أدق من Architecture لأخرى و بذلك تكون وصلت إلى ما تريد.

الـ Length Modifier هى :

signed short
signed long
signed long long
unsigned short
unsigned long
unsigned long long

• يوجد نوع بيانات واحد للأرقام الصحيحة و هو int و يمكننا تغيير المدى الخاص به عن طريق الـ Length Modifier لنحصل على أنواع جديدة مشتقة منه و هي short و long و long long كأن نكتب:

short int
long int
long long int

• اللغة لا تحدد حجم البيانات لأنواع البيانات و لكنها تحدد القيمة العظمى و الصغرى للأنواع الرقمية و نظرا لأن القيمة العظمى و الصغرى لهم تستهلك مساحات بقدر 2 و 4 و 8 بايت فقد تم التعارف على أن أحجام البيانات لهم هي بالمساحات السابق ذكرها و يمكنك مراجعة الملف limits.h (خاص بلغة c) و الفئة numeric_limits (خاصة بلغة cpp) حتى تتعرف بشكل أكبر على هذه الأنواع.

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

• إذا قمت بالنظر داخل الملف limits.h أو الفئه numeric_limits ستجد أنه يعطيك المدى المسموح به من الأرقام لنوع معين و هو ما تشترطه اللغة, أما المساحة التي يحجزها من الذاكرة لتمثيل ذلك المدى فهي تعود للمترجم و يمكن أن تختلف من أحدهم لآخر.

أرجو أن أكون قد أفدتك, بالتوفيق

تم تعديل هذه المشاركة بواسطة أحمد الشنقيطي في 28 يونيو 2012 في 00:13

#12
اقتباس

أرجو أن أكون قد أفدتك

نعم استفدت ..جزاك الله خيرا ..

أعتذر منك على الوقت والجهد الذي تبذله للإجابة عل أسئلتي ... ربما هناك ما هو أكثر أهمية من ذلك ...

فشكرا جزيلا لك ... وإن شاء الله أكون عند حسن ظنكblush.gif

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

#13

لا شكر على واجب أخي مصطفى :)

كلنا يستفيد من الآخر و نحن هنا لتبادل المعلومات :happy:

.. أراك في موضوع الأعداد التتابعية :D

تحياتي.

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

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…