दिलचस्प पोस्ट
फोन में फोनगैप खुला लिंक Linux में सिस्टम डेमन के रूप में मैं पर्ल स्क्रिप्ट कैसे चला सकता हूँ? एंड्रॉइड ऐप में ग्रिडव्यू वीएस ग्रिड लेआउट रेल 4 नेस्टेड विशेषताएँ Unpermitted पैरामीटर अलार्म प्रबंधक पहले से ही एक अलार्म सेट क्या है की जांच कैसे करें? क्या मुझे सफलता और त्रुटि के बजाय नए jQuery AJAX कोड के लिए। () और .fail () का उपयोग करना चाहिए कैसे 'स्थानीय चर को प्रारंभ नहीं किया जा सकता है' से बचने के लिए? कैसे स्क्रॉल दिशा का पता लगाने के लिए स्विफ्ट में NSURL सत्र डाउनलोड टास्क का उपयोग करते हुए बहुसंख्यक फ़ाइलों को डाउनलोड करने के लिए कैसे करें मैं एक आयात लाइब्रेरी (.lib) और दृश्य सी ++ में एक DLL कैसे बना सकता हूं? एक .NET धागा को मारना मैं विधि के बजाय मेरी कक्षा के शीर्ष पर मेरी चर सेट करना चाहूंगा KeyListener JPanel के लिए काम नहीं कर रहा है एक्स स्ट्रॉन्ग एक्सट्रैक्ट की तलाश में है ओपनसीवी 3.0 के साथ लिंक करते समय 'अनसुलझे बाहरी प्रतीक' त्रुटि

मनमाना-सटीक अंकगणितीय स्पष्टीकरण

मैं सी सीखने की कोशिश कर रहा हूं और वास्तव में बड़ी संख्या (अर्थात, 100 अंक, 1000 अंक, आदि) के साथ काम करने में असमर्थता में आ गया हूं। मुझे पता है कि ऐसा करने के लिए पुस्तकालय मौजूद हैं, लेकिन मैं इसे खुद को लागू करने का प्रयास करना चाहता हूं

मैं सिर्फ इतना जानना चाहता हूं कि किसी व्यक्ति को मनमाना-सटीक अंकगणित के विस्तृत विवरण, गूढ़ नीचे स्पष्टीकरण प्रदान किया जा सकता है या नहीं।

वेब के समाधान से एकत्रित समाधान "मनमाना-सटीक अंकगणितीय स्पष्टीकरण"

संख्याएं छोटे भागों के रूप में रखने के लिए पर्याप्त भंडारण और एल्गोरिदम के मामले हैं। मान लीजिए कि आपके पास एक कंपाइलर है जिसमें एक int केवल 0 से 99 हो सकता है और आप 999999 तक नंबर संभाल करना चाहते हैं (हम केवल इसे सकारात्मक रखने के लिए सकारात्मक संख्याओं के बारे में चिंता करेंगे)।

आप ऐसा करते हैं कि प्रत्येक नंबर तीन int नंबर देकर और समान नियमों का उपयोग कर आप (होना चाहिए) प्राथमिक विद्यालय में इसके अलावा, घटाव और अन्य बुनियादी कार्यों के लिए वापस सीखा है।

एक मनमाने ढंग से सटीक पुस्तकालय में, हमारे नंबरों का प्रतिनिधित्व करने के लिए उपयोग किए जाने वाले मूल प्रकार की संख्या पर कोई निश्चित सीमा नहीं है, जो कुछ भी हो सकता है स्मृति को रोक सकता है।

उदाहरण के लिए जोड़: 123456 + 78 :

 12 34 56 78 -- -- -- 12 35 34 

कम से कम महत्वपूर्ण अंत से कार्य करना:

  • प्रारंभिक ले जाने = 0
  • 56 + 78 + 0 कैरी = 134 = 34 के साथ 1 कैरी
  • 34 + 00 + 1 लेयर = 35 = 35 के साथ 0 लेयर
  • 12 + 00 + 0 लेयर = 12 = 12 के साथ 0 ले

यह वास्तव में, यह कैसे आम तौर पर आपके सीपीयू के अंदर बिट स्तर पर काम करता है।

घटाव समान है (आधार प्रकार के घटाव का उपयोग करना और ले जाने के बजाय उधार लेना), गुणा दोहराया अतिरिक्त (बहुत धीमा) या क्रॉस-प्रोडक्ट्स (तेज़) के साथ किया जा सकता है, और विभाजन जटिल है, लेकिन संख्याओं के स्थानांतरण और घटाव के द्वारा किया जा सकता है शामिल (आप एक बच्चे के रूप में सीखा होगा लंबी विभाजन)

मैंने वास्तव में पुस्तकालयों को दस प्रकार की अधिकतम शक्तियों का उपयोग करने के लिए लाइब्रेरी लिखी है, जो एक पूर्णांक में फिट हो सकते हैं, जब स्क्वेर्ड (अतिप्रवाह को रोकने के लिए जब दो int को एक साथ गुणा किया जाता है, जैसे कि 16-बिट int 0 तक सीमित है 99 9, 801 (<32,768) जब स्क्वायर, या 32-बिट int 0 से 9, 99 9 तक 99 9 80,001 (<2,147,483,648) उत्पन्न करने के लिए उत्पन्न करता है जो कि एल्गोरिदम को बहुत कम करता है।

कुछ युक्तियां देखने के लिए

1 / जब संख्याओं को जोड़ना या बढ़ाना, तो अधिकतम आवश्यक स्थान को पहले आवंटित करें, फिर बाद में कम करें यदि आपको लगता है कि यह बहुत अधिक है। उदाहरण के लिए, दो 100- "अंक" (जहां संख्या एक int ) जोड़ना आपको 101 अंकों से अधिक नहीं देगी। एक 3 अंकों की संख्या से 12-अंकों की संख्या को गुणा करें, कभी भी 15 अंकों से अधिक अंक न बनाएं (अंक की संख्या जोड़)।

2 / अतिरिक्त गति के लिए, सामान्य (आवश्यक भंडारण को कम करने के लिए) संख्या केवल तभी आवश्यक है – मेरी लाइब्रेरी को एक अलग कॉल के रूप में यह था ताकि उपयोगकर्ता गति और भंडारण की चिंताओं के बीच निर्णय ले सके।

3 / एक सकारात्मक और ऋणात्मक संख्या को जोड़ना घटाव है, और एक ऋणात्मक संख्या को घटाकर समकक्ष सकारात्मक जोड़ना है। संकेतों को एडजस्ट करने के बाद आप एक दूसरे को कॉल करके जोड़कर और घटाना तरीके से कोड का काफी थोड़ा बचा सकते हैं।

4 / छोटे लोगों से बड़ी संख्याओं को घटाना से बचें, क्योंकि आप हमेशा संख्याओं के साथ समाप्त होते हैं जैसे:

  10 11- -- -- -- -- 99 99 99 99 (and you still have a borrow). 

इसके बजाय, 11 से 10 घटाएं, फिर इसे नकार दें:

 11 10- -- 1 (then negate to get -1). 

यहां दिए गए एक पुस्तकालयों में से एक (पाठ में बदल गया) मुझे इसके लिए करना था यह कोड दुर्भाग्यवश, कॉपीराइट है, लेकिन आप चार मूल आपरेशनों को संभालने के लिए पर्याप्त जानकारी चुन सकते हैं। निम्नलिखित में मान लें कि -a और -b नकारात्मक संख्याओं का प्रतिनिधित्व करते हैं और a और b शून्य या सकारात्मक नंबर होते हैं।

इसके अतिरिक्त , यदि संकेत भिन्न हैं, तो अस्वीकृति का घटाव का उपयोग करें:

 -a + b becomes b - a a + -b becomes a - b 

घटाव के लिए , यदि संकेत भिन्न होते हैं, तो अस्वीकृति के अतिरिक्त उपयोग करें:

  a - -b becomes a + b -a - b becomes -(a + b) 

साथ ही यह सुनिश्चित करने के लिए विशेष हैंडलिंग भी है कि हम बड़ी संख्या से छोटी संख्या घटा रहे हैं:

 small - big becomes -(big - small) 

गुणा प्रविष्टि स्तर के गणित का उपयोग निम्नानुसार करता है:

 475(a) x 32(b) = 475 x (30 + 2) = 475 x 30 + 475 x 2 = 4750 x 3 + 475 x 2 = 4750 + 4750 + 4750 + 475 + 475 

जिस तरीके से यह हासिल किया जाता है, उसमें 32 में से प्रत्येक अंक एक बार (पीछे की तरफ) से निकालना शामिल होता है, फिर परिणाम के शुरू होने के लिए मूल्य (शुरू में शून्य) में जोड़ने के लिए जोड़ का उपयोग करना।

ShiftLeft और ShiftRight परिचालन का उपयोग LongInt वैल्यू (10 "" वास्तविक "गणित" के लिए) द्वारा एक LongInt को गुणा या विभाजित करने के लिए किया जाता है। उपरोक्त उदाहरण में, 9 5 9 (परिणाम = 0 + 950 = 950) प्राप्त करने के लिए हम 475 से शून्य 2 बार (32 का अंतिम अंक) जोड़ते हैं।

फिर हम 4750 पाएं और 4750 पाएं और दाएं शिफ्ट 32 को पाने के लिए छोड़ दिया। 14250 प्राप्त करने के लिए 4750 से शून्य को 3 गुणा करो और 1550 प्राप्त करने के लिए 950 के परिणाम में जोड़ें।

वाम पाल 4750 47500 प्राप्त करने के लिए, सही बदलाव 3 को प्राप्त करने के लिए। चूंकि सही स्थानांतरित 32 अब शून्य है, हम समाप्त हो गए हैं, और वास्तव में, 475 x 32 बराबर 15200 है।

डिवीजन भी मुश्किल है लेकिन शुरुआती अंकगणितीय ("गज़िता" विधि के लिए "में जाता है") पर आधारित है। 12345/27 के लिए निम्नलिखित लंबी डिवीजन पर विचार करें:

  457 +------- 27 | 12345 27 is larger than 1 or 12 so we first use 123. 108 27 goes into 123 4 times, 4 x 27 = 108, 123 - 108 = 15. --- 154 Bring down 4. 135 27 goes into 154 5 times, 5 x 27 = 135, 154 - 135 = 19. --- 195 Bring down 5. 189 27 goes into 195 7 times, 7 x 27 = 189, 195 - 189 = 6. --- 6 Nothing more to bring down, so stop. 

इसलिए 12345 / 27 बाकी 6 साथ 457 । सत्यापित करें:

  457 x 27 + 6 = 12339 + 6 = 12345 

यह एक बार में 12345 के खंड को नीचे लाने के लिए ड्रॉ-डाउन वेरिएबल (शुरू में शून्य) का उपयोग करके कार्यान्वित किया जाता है जब तक कि यह 27 से अधिक या उसके बराबर नहीं हो।

तब हम केवल उस 27 से घटाते हैं जब तक कि हम 27 से कम नहीं होते – घटाव की संख्या शीर्ष पंक्ति में जोड़ा गया खंड है

जब नीचे लाने के लिए कोई और खंड नहीं हैं, तो हमारे पास हमारा परिणाम है


ध्यान रखें ये सुंदर बुनियादी एल्गोरिदम हैं अगर आपके नंबर विशेष रूप से बड़े होने जा रहे हैं, तो जटिल अंकगणित करने के लिए बेहतर तरीके हैं आप जीएनयू मल्टीपल प्रेसिजन अरथमेटिक लाइब्रेरी की तरह कुछ देख सकते हैं – यह मेरी खुद की लाइब्रेरी से काफी बेहतर और तेज है

इसके बदले में दुर्भाग्यपूर्ण गलतफहमी होती है, अगर यह स्मृति से बाहर निकलती है (मेरी राय में सामान्य प्रयोजन पुस्तकालय के लिए एक घातक दोष है), लेकिन यदि आप पिछले देख सकते हैं, तो यह क्या करता है पर बहुत अच्छा है।

यदि आप इसका लाइसेंसिंग कारणों के लिए उपयोग नहीं कर सकते हैं (या क्योंकि आप अपने आवेदन को बिना किसी स्पष्ट कारण से बाहर निकल जाना चाहते हैं), तो आप अपने स्वयं के कोड में एकीकरण के लिए कम से कम एल्गोरिदम प्राप्त कर सकते हैं।

मैंने यह भी पाया है कि एमपीआइआर (जीएमपी का एक कांका) पर मौजूद बोदों को संभावित परिवर्तनों पर चर्चा करने के लिए अधिक अनुकूल है – वे एक अधिक डेवलपर-अनुकूल गुच्छा लगते हैं।

जबकि पहिया का फिर से खोजना आपके व्यक्तिगत प्रवर्तन और सीखने के लिए बहुत अच्छा है, यह भी एक बहुत बड़ा काम है। मैं आपको इसे एक महत्वपूर्ण अभ्यास और एक जो मैंने खुद किया है, के साथ अव्यवहार करना नहीं चाहता, लेकिन आपको पता होना चाहिए कि काम में सूक्ष्म और जटिल समस्याएं हैं, जो बड़े पैकेज का पता लगाते हैं।

उदाहरण के लिए, गुणन। नैवेली, आप 'स्कूली बेटी' पद्धति के बारे में सोच सकते हैं, यानी दूसरे के ऊपर एक नंबर लिखें, फिर स्कूल में सीखने के साथ-साथ लंबे गुणा करें। उदाहरण:

  123 x 34 ----- 492 + 3690 --------- 4182 

लेकिन यह विधि बेहद धीमी है (ओ (एन ^ 2), एन अंकों की संख्या है)। इसके बजाय, आधुनिक बिग्नम संकुल एक असतत फूरियर ट्रांस्फ़ॉर्म या न्यूमेरिक ट्रांस्फ़ॉर्म का उपयोग या तो अनिवार्य रूप से हे (एन एल एन (एन)) ऑपरेशन में बदलने के लिए करते हैं।

और यह सिर्फ पूर्णांक के लिए है जब आप संख्या के वास्तविक प्रतिनिधित्व (लॉग, sqrt, exp, आदि) के कुछ प्रकार पर और अधिक जटिल कार्यों में आते हैं तो और भी जटिल हो जाते हैं।

यदि आप कुछ सैद्धांतिक पृष्ठभूमि चाहते हैं, तो मैं अत्यधिक यैप की पुस्तक "फंडामेंटल प्रॉब्लम्स ऑफ़ एल्गोरिथम अल्जीब्रा" के पहले अध्याय को पढ़ने की सलाह देता हूं। जैसा कि पहले ही उल्लेख किया गया है, जीएमपी बिग्नम पुस्तकालय एक उत्कृष्ट पुस्तकालय है। वास्तविक संख्या के लिए, मैंने mpfr का उपयोग किया है और इसे पसंद किया है।

पहिया को फिर से न बदलें: यह चौकोर हो सकता है!

तीसरी पार्टी की लाइब्रेरी का प्रयोग करें, जैसे कि जीएनयू एमपी , जिसे कोशिश और परीक्षण किया जाता है।

आप इसे गणित के हाई स्कूल स्तर के साथ कर सकते हैं हालांकि अधिक उन्नत एल्गोरिदम वास्तविकता में उपयोग किया जाता है उदाहरण के लिए, दो 1024-बाइट नंबर जोड़ने के लिए:

 unsigned char first[1024], second[1024], result[1025]; unsigned char carry = 0; unsigned int sum = 0; for(size_t i = 0; i < 1024; i++) { sum = first[i] + second[i] + carry; carry = sum - 255; } 

अधिकतम मूल्यों का ख्याल रखने के लिए इसके अलावा परिणाम one place बड़ा होना होगा। इसे देखो :

 9 + 9 ---- 18 

यदि आप सीखना चाहते हैं तो टीटीमैथ एक महान पुस्तकालय है इसे C ++ का उपयोग करके बनाया गया है उपरोक्त उदाहरण एक मूर्खतापूर्ण था, लेकिन यह सामान्य रूप से जोड़ और घटाव कैसे किया जाता है!

इस विषय के बारे में एक अच्छा संदर्भ गणितीय संचालन की कम्प्यूटेशनल जटिलता है । यह आपको बताता है कि प्रत्येक ऑपरेशन के लिए कितना स्थान आवश्यक है जिसे आप लागू करना चाहते हैं। उदाहरण के लिए, यदि आपके पास दो N-digit संख्याएं हैं, तो आपको गुणन के परिणाम को स्टोर करने के लिए 2N digits आवश्यकता है।

जैसा कि मिच ने कहा, यह लागू करने के लिए एक आसान काम नहीं है! मैं आपको टीटीमैथ पर एक नज़र डालता हूं यदि आप सी ++ जानते हैं

आप इसे मूल रूप से उसी तरह करते हैं जैसे आप पेन्सिल और पेपर के साथ करते हैं …

  • बफर (एरे) में एक मनमाना आकार (जो कि malloc और realloc का उपयोग करने का अर्थ है) को लेने के लिए आवश्यक संख्या में प्रतिनिधित्व किया जाता है
  • आप मूलभूत अंकगणित को भाषा समर्थित संरचनाओं का उपयोग करके जितना संभव कर सकते हैं, और साथ सौदा करने और मूलांक-बिंदु को मैन्युअल रूप से आगे बढ़ाना
  • आप अधिक जटिल कार्य से निपटने के लिए कुशल तर्कों को खोजने के लिए संख्यात्मक विश्लेषण ग्रंथों को निकालते हैं
  • आप जितना चाहें उतना ही लागू करते हैं

आम तौर पर आप गणना के मूल इकाई के रूप में उपयोग करेंगे

  • 0-99 या 0-255 युक्त बाइट्स
  • 16 बिट शब्द contaning 0-9999 या 0–65536 सूख
  • जिसमें 32 बिट शब्द हैं …

जैसा कि आपके वास्तुकला द्वारा निर्धारित

द्विआधारी या दशमलव आधार की पसंद आप पर निर्भर करता है कि अधिकतम अंतरिक्ष दक्षता, मानव पठनीयता, और आपकी चिप पर बाइनरी कोडित दशमलव (बीसीडी) गणित का समर्थन नहीं है।

परम संदर्भों में से एक (आईएमएचओ) है न्युट का टीएओओसीपी खंड II। यह इन अभ्यावेदनों पर संख्याओं और अंकगणितीय कार्यों का प्रतिनिधित्व करने के लिए बहुत सारे एल्गोरिदम बताता है।

 @Book{Knuth:taocp:2, author = {Knuth, Donald E.}, title = {The Art of Computer Programming}, volume = {2: Seminumerical Algorithms, second edition}, year = {1981}, publisher = {\Range{Addison}{Wesley}}, isbn = {0-201-03822-6}, } 

यह मानते हुए कि आप अपने आप को एक बड़ा पूर्णांक कोड लिखना चाहते हैं, यह आश्चर्यजनक रूप से सरल है, जो कि इसे हाल ही में किया था (हालांकि MATLAB में है)। यहां कुछ युक्तियां हैं जो मैंने इस्तेमाल की हैं:

  • मैंने प्रत्येक व्यक्ति के दशमलव अंकों को एक दोहरी संख्या के रूप में संग्रहित किया है। यह कई कार्यों को सरल बनाता है, खासकर आउटपुट यद्यपि यह आपकी इच्छानुसार अधिक भंडारण लेता है, यहां मेमोरी सस्ती है, और यह गुणन बहुत कुशल बनाता है यदि आप वैक्टर की एक जोड़ी को कुशलतापूर्वक समझा सकते हैं वैकल्पिक रूप से, आप कई दशमलव अंकों को दोहरे में संग्रहीत कर सकते हैं, लेकिन सावधान रहें कि गुणा करने के लिए रूपांतरण बहुत बड़ी संख्या में संख्यात्मक समस्याएं पैदा कर सकता है।

  • एक हस्ताक्षर बिट अलग से स्टोर करें

  • दो संख्याओं का जोड़ मुख्य रूप से अंकों को जोड़ने का मामला है, फिर प्रत्येक चरण में ले जाने की जांच करें।

  • संख्याओं की एक जोड़ी का गुणन सबसे अच्छा किया जाता है, जिसके बाद कैरोलिवेशन के बाद एक कदम उठता है, कम से कम अगर आपके पास टैप पर तेजी से रूपांतरण कोड है

  • यहां तक ​​कि जब आप संख्याओं को अलग-अलग दशमलव अंकों की एक स्ट्रिंग के रूप में संग्रहीत करते हैं, तब भी डिवीजन (भी आधुनिक / रीम ऑप्स) परिणाम में लगभग 13 दशमलव अंकों के एक बार प्राप्त करने के लिए किया जा सकता है। यह एक विभाजन से अधिक कुशल होता है जो एक समय में केवल 1 दशमलव अंक पर काम करता है।

  • पूर्णांक की पूर्णांक शक्ति की गणना करने के लिए, प्रतिपादक के द्विआधारी प्रतिनिधित्व की गणना करें तब आवश्यकतानुसार शक्तियों की गणना करने के लिए बार-बार स्क्वरिंग संचालन का उपयोग करें

  • कई ऑपरेशन (फैक्टरिंग, प्राइमिलिटी टेस्ट आदि) को पॉवरमोड ऑपरेशन से लाभ होगा। यही है, जब आप मॉड (एक ^ पी, एन) की गणना करते हैं, तो एक्सपोनेंटीनिशन के प्रत्येक चरण पर परिणाम मॉड एन कम करते हैं, जहां पी को द्विआधारी रूप में व्यक्त किया गया है। एक ^ p की गणना न करें, और फिर इसे मॉड एन को कम करने का प्रयास करें

यहाँ एक सरल (सरल) उदाहरण मैंने PHP में किया है

मैंने "जोड़ें" और "गुणा" को कार्यान्वित किया और एक एक्सपोनेंट उदाहरण के लिए इसका इस्तेमाल किया।

http://adevsoft.com/simple-php-arbitrary-precision-integer-big-num-example/

कोड कटाव

 // Add two big integers function ba($a, $b) { if( $a === "0" ) return $b; else if( $b === "0") return $a; $aa = str_split(strrev(strlen($a)>1?ltrim($a,"0"):$a), 9); $bb = str_split(strrev(strlen($b)>1?ltrim($b,"0"):$b), 9); $rr = Array(); $maxC = max(Array(count($aa), count($bb))); $aa = array_pad(array_map("strrev", $aa),$maxC+1,"0"); $bb = array_pad(array_map("strrev", $bb),$maxC+1,"0"); for( $i=0; $i<=$maxC; $i++ ) { $t = str_pad((string) ($aa[$i] + $bb[$i]), 9, "0", STR_PAD_LEFT); if( strlen($t) > 9 ) { $aa[$i+1] = ba($aa[$i+1], substr($t,0,1)); $t = substr($t, 1); } array_unshift($rr, $t); } return implode($rr); }