एक मजेदार चुनौती। :)
मुझे लगता है कि आप मनमाने ढंग से लंबाई के पूर्णांक चाहते हैं। मैं निम्नलिखित दृष्टिकोण का सुझाव देता हूं:
डेटाटाइप "इंट" के द्विआधारी प्रकृति पर विचार करें। चीजों को जोड़ने पर आपके सीपीयू में सर्किट क्या करते हैं, इसका अनुकरण करने के लिए सरल बाइनरी ऑपरेशन का उपयोग करने के बारे में सोचें। यदि आप अधिक गहराई से रुचि रखते हैं, तो आधे हिस्से और पूर्ण-जोड़ने वालों पर इस विकिपीडिया लेख को पढ़ने पर विचार करें । आप ऐसा ही कुछ कर रहे होंगे, लेकिन आप निम्न स्तर के रूप में नीचे जा सकते हैं - लेकिन आलसी होने के नाते, मैंने सोचा कि मैं बस आगे बढ़ना चाहता हूं और एक सरल समाधान भी ढूंढ सकता हूं।
लेकिन जोड़ने, घटाने, गुणा करने के बारे में किसी भी एल्गोरिथम विवरण में जाने से पहले, आइए कुछ डेटा संरचना खोजें। एक सरल तरीका है, निश्चित रूप से, एक std :: वेक्टर में चीजों को स्टोर करने के लिए।
template< class BaseType >
class BigInt
{
typedef typename BaseType BT;
protected: std::vector< BaseType > value_;
};
यदि आप एक निश्चित आकार के वेक्टर बनाना चाहते हैं और इसे प्रचारित करना चाहते हैं तो आप इस पर विचार कर सकते हैं। कारण यह है कि विभिन्न कार्यों के लिए, आपको वेक्टर के प्रत्येक तत्व - ओ (एन) से गुजरना होगा। आप यह जानना चाह सकते हैं कि एक ऑपरेशन कितना जटिल है और एक निश्चित एन ही करता है।
लेकिन अब संख्याओं पर काम करने के लिए कुछ एल्गोरिदम। आप इसे तर्क-स्तर पर कर सकते हैं, लेकिन हम परिणामों की गणना करने के लिए उस जादुई CPU शक्ति का उपयोग करेंगे। लेकिन हम हाफ- और फुलएडर्स के लॉजिक-इलस्ट्रेशन से जो कुछ लेंगे, वह है कि यह किस तरह से किया जाता है। एक उदाहरण के रूप में, विचार करें कि आप + = ऑपरेटर को कैसे लागू करेंगे । BigInt में प्रत्येक संख्या के लिए <> :: value_, आप उन्हें जोड़ेंगे और देखेंगे कि क्या परिणाम कुछ प्रकार के कैरी का उत्पादन करता है। हम इसे थोड़ा समझदार नहीं करेंगे, लेकिन हमारे बेसटाइप की प्रकृति पर भरोसा करें (यह लंबे या इंट या कम या जो भी हो): यह ओवरफ्लो होता है।
निश्चित रूप से, यदि आप दो संख्याएँ जोड़ते हैं, तो परिणाम उन संख्याओं में से एक से अधिक होना चाहिए, है ना? यदि ऐसा नहीं है, तो परिणाम बह निकला।
template< class BaseType >
BigInt< BaseType >& BigInt< BaseType >::operator += (BigInt< BaseType > const& operand)
{
BT count, carry = 0;
for (count = 0; count < std::max(value_.size(), operand.value_.size(); count++)
{
BT op0 = count < value_.size() ? value_.at(count) : 0,
op1 = count < operand.value_.size() ? operand.value_.at(count) : 0;
BT digits_result = op0 + op1 + carry;
if (digits_result-carry < std::max(op0, op1)
{
BT carry_old = carry;
carry = digits_result;
digits_result = (op0 + op1 + carry) >> sizeof(BT)*8;
}
else carry = 0;
}
return *this;
}
अन्य अंकगणितीय ऑपरेशन अनुरूप होते हैं। हेक, आप भी stl- फंक्शनलर्स का उपयोग कर सकते हैं std :: plus and std :: minus, std :: times और std :: divide, ..., लेकिन कैरी को माइंड करें। :) आप अपने प्लस और माइनस ऑपरेटरों का उपयोग करके गुणन और विभाजन को भी लागू कर सकते हैं, लेकिन यह बहुत धीमा है, क्योंकि इससे आपको प्रत्येक कॉल में पहले से प्लस और माइनस करने के लिए पहले से कॉल किए गए परिणामों की पुनर्गणना होगी। इस सरल कार्य के लिए बहुत सारे अच्छे एल्गोरिदम हैं, विकिपीडिया या वेब का उपयोग करें ।
और निश्चित रूप से, आपको मानक ऑपरेटरों को लागू करना चाहिए जैसे कि operator<<
(बस प्रत्येक मूल्य को मूल्य में_ को n बिट्स के लिए बाईं ओर स्थानांतरित कर दें value_.size()-1
... ओह से शुरू करें और कैरी को याद रखें :), operator<
- आप यहां थोड़ा अनुकूलन भी कर सकते हैं, जाँच कर सकते हैं size()
पहले के साथ अंकों की संख्या । और इसी तरह। फिर अपनी कक्षा को उपयोगी बनायें, दोस्ती से std :: ostream operator<<
।
आशा है कि यह दृष्टिकोण सहायक है!