Project Euler Homework

056_bigN.h

00001 #ifndef _INCL_BIGN
00002 #define _INCL_BIGN
00003 #include <iostream>
00004 #include<iomanip>
00005 using namespace std;
00006 
00007 unsigned
00008 reverseBit (unsigned a)
00010 {
00011   unsigned b = 1;               //equals to 1(bin)
00012   for (; a; a >>= 1)            // a not zero
00013     {
00014       b <<= 1;
00015       b |= a & 1;
00016     }
00017   return b;
00018 }
00019 
00020 inline void
00021 printError ()
00022 {
00023   cout << "Error: overflow" << endl;
00024 }
00025 
00026 typedef unsigned long long verylong;
00027 const verylong bigN_limit = 1e8;
00028 const unsigned bigN_precision = 8;      //1e18;
00029 const int bigN_gps = 30;        //must be even number
00030 class bigN056
00037 {
00038 protected:
00039   verylong mantissa[bigN_gps];
00040 public:
00041   bigN056 ();
00042   bigN056 (unsigned);
00043   void operator*= (unsigned);
00044   void operator+= (bigN056 &);
00045   void square ();
00046   verylong operator[] (int);
00047   void pow (unsigned);
00048   void printN ();
00049   bool isOverflow ();
00050 };
00051 
00052 bigN056::bigN056 ()
00053 {
00054   for (int k = 0; k < bigN_gps; k++)
00055     mantissa[k] = 0;
00056 }
00057 
00058 bigN056::bigN056 (unsigned y)
00059 {
00060   mantissa[0] = y;
00061   for (int k = 1; k < bigN_gps; k++)
00062     mantissa[k] = 0;
00063 }
00064 
00065 verylong bigN056::operator[](int i)
00066 {
00067   return mantissa[i];
00068 }
00069 
00070 void
00071 bigN056::square ()
00072 {
00073   if (mantissa[bigN_gps / 2 + 1] != 0)  //overflow
00074     printError ();
00075 
00076   verylong mantissa2[bigN_gps];
00077 
00078   for (int i = 0; i < bigN_gps; i++)
00079     mantissa2[i] = 0;
00080 
00081   for (int i = 0; i < bigN_gps / 2; i++)
00082 
00083     for (int j = 0; j < bigN_gps / 2; j++)
00084       {
00085         mantissa2[i + j] += mantissa[i] * mantissa[j];
00086         if (mantissa2[i + j] >= bigN_limit)     //carry in
00087           {
00088             mantissa2[i + j + 1] += mantissa2[i + j] / bigN_limit;
00089             mantissa2[i + j] %= bigN_limit;
00090           }
00091       }
00092 
00093   if (isOverflow ())            //overflow
00094     printError ();
00095 
00096 //copy back
00097   for (int i = 0; i < bigN_gps; i++)
00098     mantissa[i] = mantissa2[i];
00099 }
00100 
00101 void
00102 bigN056::pow (unsigned y)
00103 {
00104   bigN056 result (1);
00105   verylong x = mantissa[0];     //WARNING: assume the number is very small ********
00106   for (unsigned k = reverseBit (y); k > 1; k >>= 1)
00107     {
00108       if (k & 1)
00109         result *= x;
00110 
00111       result.square ();
00112     }
00113   for (int i = 0; i < bigN_gps; i++)
00114     mantissa[i] = result[i];
00115 }
00116 
00117 void
00118 bigN056::operator*= (unsigned y)
00119 {
00120   for (int i = 0; i < bigN_gps; i++)
00121     mantissa[i] *= y;
00122 
00123 //carry in
00124   for (int i = 0; i < bigN_gps - 2; i++)
00125     if (mantissa[i] >= bigN_limit)
00126       {
00127         mantissa[i + 1] += mantissa[i] / bigN_limit;
00128         mantissa[i] %= bigN_limit;
00129       }
00130   if (isOverflow ())            //overflow
00131     printError ();
00132 }
00133 
00134 void
00135 bigN056::operator+= (bigN056 & Y)
00136 {
00137   for (int k = 0; k < bigN_gps; k++)
00138     mantissa[k] += Y[k];
00139   for (int k = 0; k < bigN_gps - 2; k++)
00140     if (mantissa[k] >= bigN_limit)
00141       {
00142         mantissa[k + 1] += mantissa[k] / bigN_limit;
00143         mantissa[k] %= bigN_limit;
00144       }
00145   if (isOverflow ())
00146     printError ();
00147 }
00148 
00149 void
00150 bigN056::printN ()
00151 {
00152   int k;
00153   for (k = bigN_gps - 1; k >= 0; k--)
00154     if (mantissa[k] != 0)
00155       break;
00156 
00157   cout << mantissa[k];
00158   for (k--; k >= 0; k--)
00159     cout << setfill ('0') << setw (bigN_precision) << mantissa[k];
00160 }
00161 
00162 bool
00163 bigN056::isOverflow ()
00164 {
00165   return (mantissa[bigN_gps - 1] >= bigN_limit);
00166 }
00167 
00168 ostream & operator<< (ostream & s, bigN056 & num)
00169 {
00170   num.printN ();
00171   return s;
00172 }
00173 
00174 #endif
 All Classes Files Functions Variables