فئات رقمية غاية في الطول في ++C
فئات رقمية غاية في الطول
قد تثور مواقف تتطلب استخدام أرقام تتجاوز مدي النوع unsigned long والذي هو النوع ذو المدي الأكبر في السي ++ ( حتي 4,264,967,295, أي حوالي عشرة أرقام) .
وسوف نبين لك في برنامجنا التالي طريقة لحل مشكلة كهذه فهو يتضمن فئة يمكنها أن تحوي أعدادا يصل طولها إلي مائتي رقم . وبإمكانك الوصول إلي أكثر من ذلك , بمجرد تغيير ثابت واحد هل تريد إلي ألف رقم ؟ ليس هناك مشكلة .
وحيث إن البرنامج لا يحتاج للبرامج الرسومية أو أيه دوال خاصة بالدوس , فإنه بإمكان مستخدمي بورلاند سي++ أن يستخدموا EasyWin .
الأعداد علي صورة عبارات نصية
الفئة verylong تخزن الأعداد علي في عبارة نصية ] لا تنس أن الأرقم هي أيضا محارف[ وهو ما يفسر سعتها العالية . وتحوي الفئة مصفوفة vlstr من النوع char ] مصفوفة عبارة نصية [ ومتغير عدد صحيح vlen يحوي طول العبارة النصية , وهو إجراء ليس ضروريا إلا لإراحتنا من استدعاء الدالة strlen() في كل مرة نريد فيها استعمال هذه القيمة . وتخزن الأرقام في ترتيب عكسي , بمعني أن الأحاد في العنصر 0 من المصفوفة , والعشرات في العنصر 1 , وهكذا هذا الأسلوب ييسر كثيرا عمليات التعامل مع الأعداد المخزنة في المصفوفة (أنظر الشكل )
شكل عدد بالغ الطول
وقد قدمنا دالتين فرعيتين , أحدهما لإجراء عملية الجمع , والثانية للضرب علي الأعداد المخزنة ونترك دالتي الطرح والقسمة كتدريب للقارئ .
ملف توصيف الفئة
إليك الملف التصديري المحتوي علي الفئة verylong :
Verylong.h
// verylong.h
// class specifier for very long integer type
#include <iostream>
#include <string.h> //for strlen(), etc.
#include <stdlib.h> //for ltoa()
using namespace std;
const int SZ = 1000;
//maximum digits in verylongs
class verylong
{
private:
char vlstr[SZ]; //verylong number, as a string
int vlen; //length of verylong string
verylong multdigit(const int) const; //prototypes for
verylong mult10(const verylong) const; //private functions
public:
verylong() : vlen(0) //no-arg constructor
{ vlstr[0]='\0'; }
verylong(const char s[SZ]) //one-arg constructor
{ strcpy(vlstr, s); vlen=strlen(s); } //for string
verylong(const unsigned long n) //one-arg constructor
{ //for long int
ltoa(n, vlstr, 10); //convert to string
strrev(vlstr); //reverse it
vlen=strlen(vlstr); //find length
}
void putvl() const; //display verylong
void getvl(); //get verylong from user
verylong operator + (const verylong); //add verylongs
verylong operator * (const verylong); //multiply verylongs
};
تحتوي الفئة علي ثلاث بادئات , الأولي لاستهلاك الفئة بالصفر , بإدخال المحرف الصفري في بداية المصفوفة وتحديد طولها بصفر , والثانية لاستهلاك الفئة بعبارة نصية معينة والثالثة لاستهلالها بطول معين .
ثم تحتوي الفئة علي أربع دوال عامة , دالة الإدخال ودالة الإخراج , ودالتان لزيادة تحميل مؤثري الجمع والضرب حتي يمكن استخدامها مع أعداد الفئة verylong . وأخيرا تحتوي الفئة علي دالتين خاصتين , واحدة للضرب في رقم واحد , والثانية للضرب في 10 , وسوف يستخدما لكتابة روتين عملية الضرب .
ملف الدوال المنتمية
إليك الملف verylong.cpp المحتوي علي الدوال الخاصة بالفئة :
Verylong.cpp
// verylong.cpp
// implements very long integer type
#include "verylong.h" //header file for verylong
//--------------------------------------------------------------
void verylong::putvl() const //display verylong
{
char temp[SZ];
strcpy(temp,vlstr); //make copy
cout << strrev(temp); //reverse the copy
} //and display it
//--------------------------------------------------------------
void verylong::getvl() //get verylong from user
{
cin >> vlstr; //get string from user
vlen = strlen(vlstr); //find its length
strrev(vlstr); //reverse it
}
//--------------------------------------------------------------
verylong verylong::operator + (const verylong v) //add verylongs
{
char temp[SZ];
int j;
//find longest number
int maxlen = (vlen > v.vlen) ? vlen : v.vlen;
int carry = 0; //set to 1 if sum >= 10
for(j = 0; j<maxlen; j++) //for each position
{
int d1 = (j > vlen-1) ? 0 : vlstr[j]-'0'; //get digit
int d2 = (j > v.vlen-1) ? 0 : v.vlstr[j]-'0'; //get digit
int digitsum = d1 + d2 + carry; //add digits
if( digitsum >= 10 ) //if there's a carry,
{ digitsum -= 10; carry=1; } //decrease sum by 10,
else //set carry to 1
carry = 0; //otherwise carry is 0
temp[j] = digitsum+'0'; //insert char in string
}
if(carry==1) //if carry at end,
temp[j++] = '1'; //last digit is 1
temp[j] = '\0'; //terminate string
return verylong(temp); //return temp verylong
}
//--------------------------------------------------------------
verylong verylong::operator * (const verylong v) //multiply
{ //verylongs
verylong pprod; //product of one digit
verylong tempsum; //running total
for(int j=0; j<v.vlen; j++) //for each digit in arg
{
int digit = v.vlstr[j]-'0'; //get the digit
pprod = multdigit(digit); //multiply this by digit
for(int k=0; k<j; k++) //multiply result by
pprod = mult10(pprod); // power of 10
tempsum = tempsum + pprod; //add product to total
}
return tempsum; //return total of prods
}
//--------------------------------------------------------------
verylong verylong::mult10(const verylong v) const //multiply
{ //arg by 10
char temp[SZ];
for(int j=v.vlen-1; j>=0; j--) //move digits one
temp[j+1] = v.vlstr[j]; // position higher
temp[0] = '0'; //put zero on low end
temp[v.vlen+1] = '\0'; //terminate string
return verylong(temp); //return result
}
//--------------------------------------------------------------
verylong verylong::multdigit(const int d2) const
{ //multiply this verylong
char temp[SZ]; //by digit in argument
int j, carry = 0;
for(j = 0; j<vlen; j++) //for each position
{ // in this verylong
int d1 = vlstr[j]-'0'; //get digit from this
int digitprod = d1 * d2; //multiply by that digit
digitprod += carry; //add old carry
if( digitprod >= 10 ) //if there's a new carry,
{
carry = digitprod/10; //carry is high digit
digitprod -= carry*10; //result is low digit
}
else
carry = 0; //otherwise carry is 0
temp[j] = digitprod+'0'; //insert char in string
}
if(carry != 0) //if carry at end,
temp[j++] = carry+'0'; //it's last digit
temp[j] = '\0'; //terminate string
return verylong(temp); //return verylong
}
الدالتان putvl(), getvl() مباشرتان , ويستخدمان الدالة المكتبية strrev() لعكس العبارة النصية , وبذلك فهي تخزن معكوسة , ولكنها تظهر عادية .
ويقوم المؤثر + بإضافة عددين من الفئة كما هو واضح بالشكل حيث يبدأ الجمع من اليسار , ويخزن الحمل ويجمع عند اللزوم . وعند عدم تساوي العددين في الطول , يكمل طول الأقصر منهما بأصفار .
شكل جمع أعداد من الفئة verylong
ويقوم المؤثر * بإجراء عملية الضرب , ويستخدم الدالة multdigit() لضرب العددين , ثم الدالة mult10() عددا من المرات بالقدر اللازم لإزاحة العلامة العشرية وإضافة الأصفار وتضاف نتائج عمليات الضرب أولا بأول .
البرنامج التطبيقي
إليك برنامجا تطبيقيا يستخدم الملفين السابقين , وسوف نستخدمه لإجراء عملية المفكوك cl_app.cpp
في هذا البرنامج المتغير fact فقط من النوع verylong , وحين ننفذ الأمر :
Fact = fact*j;
فإن المتغير j يتحول تلقائيا إلي النوع verylong عن طريق البادئة وحيدة المعامل . ولو أنك أدخلت رقما مثل 100 , فسوف تدهش لطول المرج , وفي نفس الوقت لسرعة إجراء عملية الحساب .
تعليقات
إرسال تعليق