فئات رقمية غاية في الطول في ++C

فئات رقمية غاية في الطول

قد تثور مواقف تتطلب استخدام أرقام تتجاوز مدي النوع unsigned long والذي هو النوع ذو المدي الأكبر في السي ++ ( حتي 4,264,967,295, أي حوالي عشرة أرقام) .

وسوف نبين لك في برنامجنا التالي طريقة لحل مشكلة كهذه فهو يتضمن فئة يمكنها أن تحوي أعدادا يصل طولها إلي مائتي رقم . وبإمكانك الوصول إلي أكثر من ذلك , بمجرد تغيير ثابت واحد هل تريد إلي ألف رقم ؟ ليس هناك مشكلة .

وحيث إن البرنامج لا يحتاج للبرامج الرسومية أو أيه دوال خاصة بالدوس , فإنه بإمكان مستخدمي بورلاند سي++ أن يستخدموا EasyWin .

الأعداد علي صورة عبارات نصية

الفئة verylong تخزن الأعداد علي في عبارة نصية ] لا تنس أن الأرقم هي أيضا محارف[ وهو ما يفسر سعتها العالية . وتحوي الفئة مصفوفة vlstr من النوع char ] مصفوفة عبارة نصية [ ومتغير عدد صحيح vlen يحوي طول العبارة النصية , وهو إجراء ليس ضروريا إلا لإراحتنا من استدعاء الدالة strlen() في كل مرة نريد فيها استعمال هذه القيمة . وتخزن الأرقام في ترتيب عكسي , بمعني أن الأحاد في العنصر 0 من المصفوفة , والعشرات في العنصر 1 , وهكذا هذا الأسلوب ييسر كثيرا عمليات التعامل مع الأعداد المخزنة في المصفوفة (أنظر الشكل )

Object-Oriented Programming in C   _Page_0678_Image_0001

شكل عدد بالغ الطول

وقد قدمنا دالتين فرعيتين , أحدهما لإجراء عملية الجمع , والثانية للضرب علي الأعداد المخزنة ونترك دالتي الطرح والقسمة كتدريب للقارئ .

ملف توصيف الفئة

إليك الملف التصديري المحتوي علي الفئة 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() لعكس العبارة النصية , وبذلك فهي تخزن معكوسة , ولكنها تظهر عادية .



ويقوم المؤثر + بإضافة عددين من الفئة كما هو واضح بالشكل حيث يبدأ الجمع من اليسار , ويخزن الحمل ويجمع عند اللزوم . وعند عدم تساوي العددين في الطول , يكمل طول الأقصر منهما بأصفار .



Object-Oriented Programming in C   _Page_0682_Image_0001



شكل جمع أعداد من الفئة verylong



ويقوم المؤثر * بإجراء عملية الضرب , ويستخدم الدالة multdigit() لضرب العددين , ثم الدالة mult10() عددا من المرات بالقدر اللازم لإزاحة العلامة العشرية وإضافة الأصفار وتضاف نتائج عمليات الضرب أولا بأول .



البرنامج التطبيقي



إليك برنامجا تطبيقيا يستخدم الملفين السابقين , وسوف نستخدمه لإجراء عملية المفكوك cl_app.cpp



في هذا البرنامج المتغير fact فقط من النوع verylong , وحين ننفذ الأمر :



Fact = fact*j;



فإن المتغير j يتحول تلقائيا إلي النوع verylong عن طريق البادئة وحيدة المعامل . ولو أنك أدخلت رقما مثل 100 , فسوف تدهش لطول المرج , وفي نفس الوقت لسرعة إجراء عملية الحساب .

التسميات: