Project Euler Homework
|
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