سؤال

لدي هذا الكود

#include <iostream>

using namespace std;

int main(int argc,char **argv) {

    unsigned long long num1 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995LL;
    unsigned long long num2 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996LL;
    unsigned long long num3 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997LL;
    unsigned long long num4 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998LL;
    unsigned long long num5 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999LL;

    cout << (unsigned long long)(num1 * num2 * num3 * num4 * num5) << endl;
    return 0;
}

كما يمكنك أن ترى أعدادا هائلة, لكن عندما كنت تفعل الرياضيات هناك أحصل على هذا:18446744073709551496

في وقت الترجمة أحصل على هذه التحذيرات:

warning: integer constant is too large for its type|
In function `int main(int, char**)':|
warning: this decimal constant is unsigned only in ISO C90|
...
هل كانت مفيدة؟

المحلول

ونتيجة لديك أكبر من نوع طويل - أنت بحاجة الى ان ننظر في BigInteger أو مكتبة الدقة التعسفي ، شيء من هذا القبيل برنامج الرصد العالمي

نصائح أخرى

وستكون هذه الأرقام لا تنسجم مع أنواع البيانات أي C ++. إذا كنت ترغب فقط في طباعتها، تخزين الأرقام في السلسلة. إذا كنت تريد أن تفعل الرياضيات على ذلك، العثور على مكتبة الدقة الرياضيات التعسفية واستخدام ذلك.

إذا كنت تريد الحرفية بهذا الحجم في التعليمات البرمجية الخاصة بك، عليك أن إدخالها كما سلسلة حرفية وتحميلها في فئة BIGINT من نوع ما. ليس هناك طريقة للتعبير عن الحرفية عدد صحيح الكبيرة في التعليمات البرمجية المصدر في الوقت الراهن (على الرغم من C ++ 0X سيتناول نأمل أن النقص).

إذا كنت تستخدم BigInteger مكتبة، نلقي نظرة على وظيفة stringToBigUnsigned في BigIntegerUtils.hh لبناء عدد صحيح كبير من السلسلة.

#include "BigUnsigned.hh"
#include "BigIntegerUtils.hh"     

 BigUnsigned  num1 = stringToBigUnsigned (
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999995"
    );

ماذا كنت تحاول أن تفعل ؟ هل تفهم أساسيات ثنائي عشري الأرقام ؟ لماذا 8 بت فقط يحمل القيم من 0 إلى 255, 12 بت 0 - 4095 ، وما إلى ذلك ؟ كم بت يستغرق عقد عدد كنت مهتما ؟ أو أفضل, كم العدد هل أنت مهتم في خلق ؟ و هل تستخدم 9s لجعل عدد أكبر ؟ ماذا عن عرافة 0xF...بدلا من ذلك ؟ إذا كنت تريد أكبر رقم غير (ضمن واحدة من معيار صحيح أنواع) لماذا لا:

غير طويل ، ب ؛

a = -1;//الذي يبدو خطأ خلط الموقعة و غير الموقعة وإنما هو صالح ، وعدد يتم تحويلها إلى غير الموقعة قبل تخزينها

ب = 0;ب--;//يفعل الشيء نفسه على النحو الوارد أعلاه

هل حقا تحتاج إلى الدقة في هذا المستوى ؟ كنت أدرك أن يضاعف يمكن أن تتطلب نتيجة ضعف حجم كل المعامل?0xFF * 0xFF = 0xFE01, إذا في هذه الحالة كنت باستخدام 8 بت الصحيحه أنت لا تستطيع أن تفعل الرياضيات.فإنه يحصل فقط على أسوأ كما يمكنك الاستمرار في ضرب 0xFF * 0xFF * 0xFF = 0xFD02FF.

ماذا تحاول أن تفعل ؟


رؤية ردك:

أنا لم أر يولر رقم 8 قبل.وفي مقابلة السؤال فإنه يأخذ فقط بضعة أسطر من التعليمات البرمجية إلى حل.


الأخرى الخاصة بك الاستجابة:

أرقام...

على الأرجح لأن لدينا 10 أصابع (وربما 10 أصابع) نكبر مع "القاعدة 10".لدينا الساعات قاعدة 60 معظمها ولكنها كانت مختلطة مع القاعدة 10 لجعله أكثر مربكة.على أي حال, قاعدة 10, يعني لكل رقم نائبا لديك واحدة من 10 أرقام فريدة من نوعها, عندما تصل إلى الحد الأقصى في المكان الذي يتدحرج إلى المكان التالي.هذا هو كل مدرسة ابتدائية الأشياء.

000
001
002
003
...
008
009
010
011
012
...

ترى كيف حق معظم أرقام 10 رموز (0,1,2,3,4,5,6,7,8,9) وعندما تصل إلى آخر رمز يبدأ أكثر من واحد إلى اليسار من الزيادات تلو الآخر.هذه القاعدة صحيح لكل قاعدة نظم الترقيم.

صحيح في قاعدة 2 إلا أن هناك فقط اثنين من الرموز ، 0 و 1

000
001
010
011
100
101
...

وينطبق الشيء نفسه على ثماني لكن 8 رموز (0,1,2,3,4,5,6,7)

000
001
002
003
004
005
006
007
010
011
012
013
...

و نفس الشيء صحيح بالنسبة عشري ، 16 الرموز(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)

000
001
002
003
004
005
006
007
008
009
00a
00b
00c
00d
00هو
00f
010
011
012
013
...

كنت على وشك الذهاب إلى أسبابه استخدام ثنائي على غيرها من القواعد (10) في أجهزة الكمبيوتر.خلاصة القول أنه من السهل أن يكون دولتين أو إيقاف تشغيله ، أو ارتفاع وانخفاض.دولة مثل اثنين من الرموز 1 و 0 في قاعدة 2.في محاولة للحفاظ على الالكترونيات ضبطها إلى أكثر من دولتين في حدود المتاح من الجهد صعبة, على الأقل كان عليه أن يكون ، إبقائها قريبة من الصفر فولت أو فوق بعض عدد قليل من فولت من السهل نسبيا ، لذلك الالكترونيات الرقمية استخدام الدولتين الثنائية.

حتى مهمة بسيطة عن الإنسان في ثنائية طويلة ينضب, بسيطة الرياضيات الصف الثاني لا يزال الكثير من الآحاد والأصفار.حتى ثماني أصبحت شعبية لأنه يسمح لك أن تفكر في مجموعات من ثلاثة اجزاء يمكنك استخدام الرموز ونحن على دراية بأرقام 0,1,2,3,4,5,6,7.ولكن مجموعات من أربعة الذي هو آخر قوة 2 ، ويعطي البشر الكثير العقلية قوة الحوسبة من ثماني ، عرافة على 4 بت والتي هي أيضا قوة 2.كان لدينا لإضافة المزيد من الرموز إلى 10 استعرنا من traditial العربية قاعدة 10 حتى 6 الأولى من الأبجدية المستخدمة.ثماني هو نادرا ما تستخدم ، يمكنك أن تخبر شخص ما العمر إذا كانوا يعتقدون ثماني بدلا من عرافة.(أنا من عرافة الجيل ولكن عملت مع تلك من ثماني جيل النضال مع عرافة لأنها لا يمكن أن تحصل من ثماني إلى ثنائي إلى عشري في أذهانهم).

قاعدة 10 في الكمبيوتر مثل الإنسان العادي التفكير في عرافة.أجهزة الكمبيوتر لا تفعل القاعدة 10 (جيد كسول البشر كانوا يفعلون bcd) ، أنها قاعدة 2.الرقم العشري 1234 في الكمبيوتر هو حقا 0x4D2 أو 0b010011010010.هذا هو قيمة ، ويقول كنت ترغب في إضافة 1234 بالإضافة إلى أعداد أخرى تحتاج تلك القيمة التي لا علاقة له مع تثبيت pvc السقف 1, 2, 3 و 4.ولكن بعد هذا الجواب على ستاكوفيرفلوو نحن لا استخدام رقم نستخدم ASCII ، لذلك 1234 في ascii هو 0x31, 0x32, 0x33, 0x34 ، وهو أمر مهم في يولر الحل افتراض 1000 أرقام تم توفير سلسلة ascii الذي يجب أن يكون أو سيكون لديك التحويل من ثنائي إلى ascii لأن المشكلة هي قاعدة 10 المشكلة وليس قاعدة 2 من حيث التعريف.

حتى تعود إلى ما كنت قد طلبت.أقول لك كان 4 بت من الذاكرة لتخزين عدد, كم رقم مخزن ؟ إذا كنت تعتقد قاعدة 10 فقط قد تعتقد أن العدد هو 9 ، لأنه يتم تدريبهم على التفكير باستخدام أكبر رمز في كل مكان تخزين, 99999 هو أكبر عدد إذا كان لديك 5 مواقع تخزين في قاعدة 10.العودة إلى أربعة أجزاء على الرغم من أكبر رمز بت واحد هو 1 ، ضع هذا الرقم في كل مكان تخزين تحصل 1111 (أربعة منها).فقط من خلال النظر في تلك أربعة منها يجب أن تكون قادرة على في عقلك ترى بسهولة ثماني وعرافة نسخة من نفس رقم 17 ثماني أو و عرافة.لمعرفة عشري يأخذ الرياضيات ، أو في هذه الحالة تحفيظ هذا الرقم هو 15 عشري.لذلك أكبر أربعة عدد بت هل يمكن أن يكون هو 0xF أو 15 لا 9.ماذا عن 8 بت ؟ 0xFF أو 255 (2 إلى 8 السلطة ناقص واحد).أكبر 16 بت ؟ 65535, الخ.

لذلك عندما تسأل كم بت تحاول استخدام هذا هو ما أعنيه.ننظر إلى هذا الرقم 99999.مرة أخرى قاعدة 10 كنت أعتقد أن هذا هو أكبر عدد ، ولكن أن الكمبيوتر هو جزء السبيل الوحيد هناك, 99999 عشري هو 0x1869F ، الذي يستغرق 17 بت من الذاكرة لتخزين أكبر 17 عدد بت يمكنك متجر 0x1FFFF وهو 131071 وهو أكبر قليلا من 99999.لذلك عندما تريد أن تفكر أعداد كبيرة الرياضيات على الكمبيوتر عليك أن تفكر الثنائية (أو عرافة).

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

تأخذ أكبر 4 بت رقم 1111(الثنائية) ، والذي هو 15 عشري.إضافة إلى أن أكبر أربعة بت عدد وتحصل على 15+15 = 30 = 0x1E أو 11110 الثنائية.لذلك إضافة إلى اثنين من أربعة بت الأرقام تحتاج إلى خمسة أجزاء لعقد الجواب.أجهزة الكمبيوتر الحفاظ على "تحمل" بت هذا بت إضافية.أساسا إضافة/طرح عدد صحيح الرياضيات وظائف في جهاز الكمبيوتر تسمح لك أن يكون N+1 بت.حتى إذا كان 32 بت الكمبيوتر لديك أساسا 33 بت إضافة/فرعي الرياضيات.

المشكلة هي ضرب وقسمة ، والتي حتى اليوم العديد من المعالجات لا تدعم (نعم كثيرة لا fpu و فقط وطرح بعض الأحيان تتكاثر ، ولكن الفجوة نادرة.ضرب وقسمة تأخذ الكثير من الالكترونيات التجارة إيقاف يمكنك القيام بها مع ويضيف وينقص في البرنامج).تأخذ أسوأ الأحوال تضاعف أربع نظام قليلا 1111 * 1111 = 11100001 لذلك يأخذ 8 بت لتخزين نتيجة 4 بت مضاعفة ، وسوف تجد بسرعة أن إذا كان لديك 4 نظام قليلا أكثر من يضاعف كنت تريد أن تفعل سيؤدي عدد التي لا يمكن تخزينها في 4 بت.لذلك عندما رأيت أنت مع 64 بت الاعداد الصحيحه (غير موقعة طويل هو في كثير من الأحيان 64 بت) و تتضاعف أربع مرات ، وهذا يعني أنك بحاجة إلى 64*5 أو 320 بت عدد صحيح إلى متجر إجابتك كنت تحاول وضع هذا الجواب في 64 نتيجة كبيرة ، والتي في كثير من الأحيان ، اعتمادا على مترجم و الكمبيوتر بسعادة لا و سيتم اقتطاع العليا بت ويترك لك مع انخفاض 64 بت من النتيجة التي يمكن بسهولة تبدو أصغر من أي من المعاملات ، وهو ما كنت قد ظننت أنك قد فعلت في الأولى.

النقطة العائمة ليس أكثر بكثير من العلمي لكن في الثنائية ، إذا أردت مضاعفة عدد 1234 و 5678 باستخدام العلمي كنت تأخذ 1.234*10^3 مرات 5.678*10^3 و الحصول على 7.007*10^6.يمكنك الاحتفاظ الخاص بك الدقة قادرة على تمثيل أوسع مجموعة من الأرقام.لن ندخل في كيف يعمل هذا في الثنائية.لكنه لا يعمل على سؤالك الأصلي.

آه, آخر شيء لتوضيح ما كنت أفعله في سؤالي/الاستجابة.سلبي الاعداد الصحيحه في الثنائية.لأن العلاقات بين الجمع والطرح و قاعدة نظم يمكنك أن تلعب بعض الحيل.أقول أردت أن اطرح 1 من رقم 7(عشري) باستخدام الثنائية.حسنا لا يوجد شيء مثل طرح الدائرة ، بدلا من ذلك يمكنك إضافة رقم سلبي وذلك بدلا من 7 - 1 هو حقا 7 + (-1) ، فإنه يجعل الفرق:

0111 + ???? = 0110

ما هو الرقم الذي يمكن أن تضيفها إلى 7 على 6...في ثنائي ؟

0111 + 1111 = 0110

الأرقام السالبة في الثنائية تسمى "ثنائي مكمل" ، قصة قصيرة طويلة الجواب هو "عكس وإضافة 1".كيف كنت تمثل ناقص 1 في ثنائي ؟ تأخذ زائد واحد 0001 ثم عكس هذا المعنى جعل تلك الواحدات و الأصفار منها (المعروف أيضا باسم تلك تكمل) 1110 ثم إضافة واحد 1111.ناقص واحد هو رقم خاص في أجهزة الكمبيوتر (حسن في كل مكان) كما لا يهم كيف العديد من القطع لديك يتم تمثيل كل منها.لذا عندما ترى شخص القيام بذلك:

char غير الموقعة ؛

a = -1;

المترجم أولا يبدو أن -1 و يفكر ...11111(ثنائي) ثم يبدو في علامة التساوي وعلى الجانب الآخر, هل تريد أن يكون كل منها ، فإنه يرى أن لديك توقيع عدد صحيح غير موقعة ولكن التحويل هو مجرد نقل البتات أكثر حتى أنت تقول أعلاه التي تريد = 0xFF;(على افتراض 8 بت char غير الموقعة).

بعض المجمعين قد يشكون من أن تحاول مخزن رقم سلبي في غير موقعة عدد.غيرها من المجمعين سوف ننظر في ذلك -1 ونرى ذلك في 32 بت أو هذه الأيام ربما 64 بت عدد صحيح ثابت ثم عندما يقيم يساوي إلى 8 بت غير موقعة سوف تحصل على تحذير من أن كنت لا يمكن تخزين -1 في موقعة أو غير موقعة تشار دون التلبيس.ولكن إذا كنت تفعل هذا:

a = 0;أ -;

جميع المجمعين سوف ترغب في ذلك.و لن يشكو فقط الحروق دورات الحاسوب في وقت التشغيل بدلا من تجميع الوقت.

الآن في مكان ما قال لي صديق من كتاب هل الرياضيات الثنائية بشكل متسلسل.على سبيل المثال أن ينفي عددا ، وعادة ما تفعل عكس الإعلانية خدعة واحدة ، ولكن مع قلم رصاص و ورقة قد يقول لكم البعض الآخر خدعة.بدءا من الحق في نسخ الأصفار بما في ذلك أول 1 ثم invert بعد ذلك لذلك ناقص 2

0010
1110

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

ناقص 6

0110
1010

ناقص 4

0100
1100

من المفترض أن هناك الحيل للقيام وطرح (حسنا نعم, تلك هي سهلة) ولكن أيضا والقسمة.إذا كنت تفعل لهم متسلسل ثم يمكنك أن تفعل بلا حدود طويلة الرياضيات في الثنائية مع نفس الو.إذا كنت تعرف كيفية القيام بذلك يمكن أن تنفذ في برنامج سؤالك الأصلي بضرب كبيرة الثوابت (مع افتراض من الحفاظ على جميع الدقة) هي تافهة على أي جهاز كمبيوتر.

والجواب الذي حصلت عليه، 18446744073709551496، ويرجع ذلك إلى 999 ... 9S يتم اقتطاع عند تعيينه لفترة طويلة طويلة، بالإضافة إلى عمليات متعددة الخاص تفيض. في حتمية، ولكن على نحو فعال مجرد مجموعة عشوائية من البتات.

وصحيح غير الموقعة يمثل كلمة النظام. اليوم، هذه الكلمة سوف ماكس خارج في أي 2 ^ 32 -1 أو 2 ^ 64-1، اعتمادا على ما إذا كان النظام الخاص بك هو 32 بت أو 64 بت. كنت تصل الحد الأقصى.

لديك لكتابة فئة bignum أو استخدام مرة واحدة 'صافية.

لماذا تفعلون هذا مشكلة على أي حال؟

والأرقام لا يمكن أن يصلح في مجموعة unsigned long long ذلك إما أنك يمكن أن تستخدم GMP المكتبة أو استخدام سلسلة لتمثيل الأعداد الكبيرة كما فعلت لحساب مضروب عدد مثل 50:

http://codepad.org/bkWNV0JC

#include <cmath>
#include <iostream>
using namespace std;
int main()
{
  unsigned int nd, nz;   
  unsigned char *ca;   
  unsigned int j, n=50, q, temp;
  int i;
  double p;
    p = 0.0;
    for(j = 2; j <= n; j++)
    {
      p += log10((double)j);  
    }
    nd = (int)p + 1;

    ca = new unsigned char[nd+1];
    if (!ca)
    {
      cout << "Could not allocate memory!!!";
      exit(0);
    }
    for (i = 1; (unsigned)i < nd; i++)
    {
      ca[i] = 0;
    }
    ca[0] = 1;

    p = 0.0;
    for (j = 2; j <= n; j++)
    {
      p += log10((double)j);   
      nz = (int)p + 1;        
      q = 0;                  
      for (i = 0;(unsigned) i <= nz; i++)
      {
        temp = (ca[i] * j) + q;
        q = (temp / 10);
        ca[i] = (char)(temp % 10);
      }
    }

    cout << "\nThe Factorial of " << n << " is: ";
    for( i = nd - 1; i >= 0; i--)
    {
      cout << (int)ca[i];
    }
  //  delete []ca;    
  return 0;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top