خیلی از وقت ها وقتی می خواهیم برنامه ای بنویسیم احتیاج داریم با اعداد خیلی بزرگ و سنگین کار کنیم که از محدوده ی نوع های زبان برنامه نویسیمون خارج است حتی در محدوده double هم قرار نمی گیره .اون موقع است که برناممون دچار مشکل می شه و متغییر هامون سرریز می کنند .
برای حل این مشکل معمولا برنامه نویسان کلاس ها و تابع هایی را می نویسند البته بعضی زبان های برنامه نویسی امکانات خوبی در اختیار می گذارند مانند پایتون که می شه باه راحتی با اعداد خیلی بزرگ کار کرد من قبلا در پستی هایی جداگانه ”پروژه ماشین حساب با عملیات روی اعداد ۱۰۰۰ رقمی با c” و “الگوریتم تقسیم اعداد بزرگ(۵۰ digit divition)” به این مشکل ها پرداخته بودم ولی اون برنامه ها زیاد سریع نبودن و برای اعداد ۱۰۰۰ رقمی بودن و محدودیت اعداد داشتند.
امروز در حال نوشتن برنامه ای بودم که احتیاج پیدا کردم که بتوانم اعداد صحیح بزرگ تر مساوی صفر را با هم جمع ، ضرب کنم و به توان هم برسانم به همین دلیل تابع هایی نوشتم که بتوان این کار را کنم و مثل قبل محدودیت کمتری داشته باشم .البته به مرور زمان هر چه در پروژه خیام و حکیم فردوسی جلو برویم این برنامه ها رو گسترش می دهیم و تقسیم و تفریق آنها را اضافه می کنیم و قابلیت اعداد منفی و اعشاری هم به آن ها می دهیم چون کار زمان بری است پله پله این کار را می کنیم.
ورودی و خروجی این توابع رشته است زیرا کار با آن ها خیلی راحت است و می توان رشته ای خیلی طولانی داشت ولی خود رشته ها هم محدودیت طول دارند دقیق یادم نیست ولی فکر کنم طولشون از ۲ میلیون هم بیشتر بشه ولی برای این مشکل می تونید از روش هایی دیگه استفاده کنید.
من تابعی به اسم Tipper نوشتم که که عدد را برعکس می کنه ولی عملیات های ریاضی به همون شکل عادی صورت می گیرد برای این این کار را کردم که کار با اعداد راحت تر شود و اگر خواستم رقمی به یک رشته اضافه کنم به تونم به راحتی از تابع push_back استفاده کنم مخصوصا وقتی که هنگام ضرب باید صفر هایی جلوی اعدا د گذاشت.
// void Tipper (string & Num) { int i; char ch; for( i=0; i< ( int(Num.size()/2)); i++) { ch = Num.at(i); Num.at(i) = Num.at( ( Num.size()- 1)-i); Num.at( ( Num.size()- 1)-i) = ch; } } //
تابع بعدی تابع جمع sum است که برای اعداد صحیح بزرگ تر مساوی صفر است
// Sum for heavy number string sum ( string Num1 , string Num2) { int i; int MaxLen; int sum=0; int r=0; char ch; string Num3; Tipper(Num1); Tipper(Num2); if(Num1.size() < Num2.size()) { MaxLen=Num2.size(); } else { MaxLen=Num1.size(); } for( i=0; i<MaxLen; i++) { sum=0; if( i< int(Num1.size())) { sum += Num1.at(i)-48; } if( i< int(Num2.size())) { sum += Num2.at(i)-48; } ch = ( (sum+r) % 10) + 48; Num3.push_back(ch); r = (sum+r) / 10; } if(r != 0) { ch = r + 48; Num3.push_back(ch); } Tipper(Num3); return Num3; } // End of Sum for heavy number
تابع بعدی تابع ضرب multiplication است این تابع دقیقا مثل ضرب کردن اعداد توسط خودمون عمل می کند و در آن از تابع جمع sum استفاده شده است ، ورودی این تابع اعداد دو رشته است و خروجی اش هم به صورت رشته است:
//Multiplication for heavy number string multiplication ( string Num1 , string Num2) { int i; int j; int t; int r = 0; int mult=0; char ch; string Num3; string Sum = "0"; Tipper(Num1); Tipper(Num2); if( Num1.size() > Num1.size()) { Num1.swap(Num2); } for ( i = 0; i < int(Num1.size()); i++) { r=0; for ( t = 0; t < i; t++) { Num3.push_back( '0'); } for ( j = 0; j < int(Num2.size()); j++) { mult = ( Num1.at(i)-48) * ( Num2.at(j)-48); ch = ( ( mult + r) % 10) + 48; Num3.push_back( ch); r = ( mult + r) / 10; } if( r != 0) { ch = r + 48; Num3.push_back( ch); } Tipper(Num3); Sum = sum( Sum, Num3); Num3.clear(); } return Sum; } //end Multiplication for heavy number
این تابع هم تابع توان power است که در آن از تابع ضرب استفاده شده است ورودی اول که رشته است پایه توان است و عدد بعدی که از نوع int است عددی است که پایه باید به توان آن برسد:
//Power for heavy number string power( string Num1, int Num2) { int i; string result = "1"; for( i=0; i<Num2; i++) { result = multiplication(result,Num1); } return result; } //end Power for heavy number
اینم کد کلی برنامه که برای مثال در آن ۲ به توان ۱۰۰۰ را حساب می کند :
// Heavy Number.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <string> using namespace std; // void Tipper (string & Num) { int i; char ch; for( i=0; i< ( int(Num.size()/2)); i++) { ch = Num.at(i); Num.at(i) = Num.at( ( Num.size()- 1)-i); Num.at( ( Num.size()- 1)-i) = ch; } } // // Sum for heavy number string sum ( string Num1 , string Num2) { int i; int MaxLen; int sum=0; int r=0; char ch; string Num3; Tipper(Num1); Tipper(Num2); if(Num1.size() < Num2.size()) { MaxLen=Num2.size(); } else { MaxLen=Num1.size(); } for( i=0; i<MaxLen; i++) { sum=0; if( i< int(Num1.size())) { sum += Num1.at(i)-48; } if( i< int(Num2.size())) { sum += Num2.at(i)-48; } ch = ( (sum+r) % 10) + 48; Num3.push_back(ch); r = (sum+r) / 10; } if(r != 0) { ch = r + 48; Num3.push_back(ch); } Tipper(Num3); return Num3; } // End of Sum for heavy number //Multiplication for heavy number string multiplication ( string Num1 , string Num2) { int i; int j; int t; int r = 0; int mult=0; char ch; string Num3; string Sum = "0"; Tipper(Num1); Tipper(Num2); if( Num1.size() > Num1.size()) { Num1.swap(Num2); } for ( i = 0; i < int(Num1.size()); i++) { r=0; for ( t = 0; t < i; t++) { Num3.push_back( '0'); } for ( j = 0; j < int(Num2.size()); j++) { mult = ( Num1.at(i)-48) * ( Num2.at(j)-48); ch = ( ( mult + r) % 10) + 48; Num3.push_back( ch); r = ( mult + r) / 10; } if( r != 0) { ch = r + 48; Num3.push_back( ch); } Tipper(Num3); Sum = sum( Sum, Num3); Num3.clear(); } return Sum; } //end Multiplication for heavy number //Power for heavy number string power( string Num1, int Num2) { int i; string result = "1"; for( i=0; i<Num2; i++) { result = multiplication(result,Num1); } return result; } //end Power for heavy number int main() { cout<<"5 ^ 1000 = "<<endl<<power("2",1000)<<endl; return 0; }
اینم حاصل ۲ به توان ۱۰۰۰ :
امیدوارم از حل این سوال لذت برده باشید اگر راهی داشتید یا برنامه ای برای این سوال نوشته اید حتما آن را برای ما ایمیل کنید یا در نظرات بنویسید ، کد شما در همین صفحه قرار خواهد گرفت با تشکر فراوان از این که ما را دنبال می کنید.