00001 #include <symbolism/N.h> 00002 #include <string> 00003 #include <sstream> 00004 00005 using namespace std; 00006 00007 namespace symbolism { 00008 namespace ring { 00009 00010 00011 const char* english_zero = "zero "; 00012 00013 const char* english_digits[20] = 00014 { 00015 "", "one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine ", 00016 "ten ", "eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen ", "eighteen ", "nineteen " 00017 }; 00018 00019 const char* english_tens[10] = 00020 { 00021 "", "ten ", "twenty ", "thirty ", "forty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety " 00022 }; 00023 00024 const char* english_hundreds[10] = 00025 { 00026 "", "hundred ", "two hundred ", "three hundred ", "four hundred ", "five hundred ", "six hundred ", "seven hundred ", "eight hundred ", "nine hundred " 00027 }; 00028 00029 const char* english_thousand = "thousand"; 00030 00031 const char* latin_digits_single[11] = 00032 { 00033 "", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion" 00034 }; 00035 00036 const char* latin_digits[10] = 00037 { 00038 "", "un-", "do-", "tre-", "quattuor-", "quin-", "sex-", "septen-", "octo-", "novem-" 00039 }; 00040 00041 const char* latin_tens[10] = 00042 { 00043 "", "dec-", "vigin-", "trigin-", "quadragin-", "quinquagin-", "sexagin-", "septuagin-", "octogin-", "nonagin-" 00044 }; 00045 00046 const char* latin_hundreds[10] = 00047 { 00048 "", "cen-", "ducen-", "trecen-", "quadringen-", "quingen-", "sescen-", "septingen-", "octingen-", "nongen-" 00049 }; 00050 00051 const char* latin_thousand = "millia-"; 00052 00053 00054 string N::to_binary() const 00055 { 00056 char* bytes = new char[(size + 1) * 64 + 1] (); 00057 unsigned char* ubytes = reinterpret_cast<unsigned char*>(bytes); 00058 int s = mpn_get_str(ubytes, 2, const_cast<limb_t*>(limbs()), size + 1); 00059 //bytes = reinterpret_cast<char*>(realloc(bytes, s + 1)); 00060 00061 for(int i=0; i < s; i++) 00062 { 00063 bytes[i] += '0'; 00064 } 00065 bytes[s] = 0x00; 00066 00067 string str(bytes); 00068 delete[] bytes; 00069 return str; 00070 } 00071 00072 string N::to_hexadecimal() const 00073 { 00074 char* bytes = new char[(size + 1) * 16 + 2] (); 00075 unsigned char* ubytes = reinterpret_cast<unsigned char*>(bytes); 00076 int s = mpn_get_str(ubytes, 16, const_cast<limb_t*>(limbs()), size + 1); 00077 //bytes = reinterpret_cast<char*>(realloc(bytes, s + 1)); 00078 00079 for(int i=0; i < s; i++) 00080 { 00081 if(bytes[i] < 10) 00082 { 00083 bytes[i] += '0'; 00084 } 00085 else 00086 { 00087 bytes[i] += 'A' - 10; 00088 } 00089 } 00090 bytes[s] = 0x00; 00091 00092 string str(bytes); 00093 delete[] bytes; 00094 return str; 00095 } 00096 00097 string N::to_decimal() const 00098 { 00099 if(this_small) 00100 { 00101 stringstream strstream; 00102 strstream << limb; 00103 return strstream.str(); 00104 } 00105 else 00106 { 00107 limb_t* cpy = new limb_t[size + 1] (); 00108 memcpy(cpy, data, (size + 1) * sizeof(limb_t)); 00109 00110 char* bytes = new char[(size + 1) * 20 + 1] (); 00111 unsigned char* ubytes = reinterpret_cast<unsigned char*>(bytes); 00112 00113 int s = mpn_get_str(ubytes, 10, cpy, size + 1); 00114 00115 // And give some back 00116 delete[] cpy; 00117 //bytes = reinterpret_cast<char*>(realloc(bytes, s + 1)); 00118 00119 for(int i=0; i < s; i++) 00120 { 00121 bytes[i] += '0'; 00122 } 00123 bytes[s] = 0x00; 00124 00125 string str(bytes); 00126 delete[] bytes; 00127 return str; 00128 } 00129 } 00130 00131 string N::to_english() const 00132 { 00133 stringstream strstream; 00134 write_english(strstream); 00135 return strstream.str(); 00136 } 00137 00138 void write_sub_thousand(ostream& out, unsigned int n) 00139 { 00140 unsigned int ones = n % 10; 00141 unsigned int tens = (n / 10) % 10; 00142 unsigned int hundreds = (n / 100) % 10; 00143 if(tens >= 2) 00144 { 00145 out << english_hundreds[hundreds] << english_tens[tens] << english_digits[ones]; 00146 } 00147 else 00148 { 00149 out << english_hundreds[hundreds] << english_digits[ones + 10 * tens]; 00150 } 00151 } 00152 00153 void write_latin_exp(ostream& out, unsigned long int n) 00154 { 00155 if(n == 0) 00156 { 00157 out << english_thousand; 00158 return; 00159 } 00160 if(n <= 10) 00161 { 00162 out << latin_digits_single[n]; 00163 return; 00164 } 00165 unsigned int groups[7]; // ln(2^64) / ln(10^3) = 00166 unsigned int ngroups = 0; 00167 while(n) 00168 { 00169 groups[ngroups] = n % 1000; 00170 n /= 1000; 00171 ngroups++; 00172 } 00173 unsigned int g = ngroups; 00174 unsigned char ones, tens, hundreds; 00175 while(--g) 00176 { 00177 if(groups[g] == 0) 00178 { 00179 continue; 00180 } 00181 if(!(g == ngroups - 1 && groups[g] == 1)) 00182 { 00183 ones = groups[g] % 10; 00184 tens = (groups[g] / 10) % 10; 00185 hundreds = (groups[g] / 100) % 10; 00186 out << latin_hundreds[hundreds] << latin_digits[ones] << latin_tens[tens]; 00187 } 00188 for(unsigned int i=0; i < g; i++) 00189 { 00190 out << latin_thousand; 00191 } 00192 } 00193 if(groups[0] == 0) 00194 { 00195 out << "tillion"; 00196 } 00197 else if(groups[0] <= 10) 00198 { 00199 out << latin_digits_single[groups[0]]; 00200 } 00201 else 00202 { 00203 ones = groups[0] % 10; 00204 tens = (groups[0] / 10) % 10; 00205 hundreds = (groups[0] / 100) % 10; 00206 out << latin_hundreds[hundreds] << latin_digits[ones] << latin_tens[tens]; 00207 00208 if(tens == 1) 00209 { 00210 out << "illion"; 00211 } 00212 else 00213 { 00214 out << "tillion"; 00215 } 00216 } 00217 } 00218 00219 void N::write_english(ostream& out) const 00220 { 00221 // Writes the integer out in english 00222 // based on: http://www.isthe.com/chongo/tech/math/number/howhigh.html 00223 00224 // Convert to base 10 00225 unsigned char* digits = new unsigned char[(size + 1) * 20 + 1] (); 00226 limb_t* cpy = new limb_t[size + 1] (); 00227 memcpy(cpy, limbs(), (size + 1) * sizeof(limb_t)); 00228 int ndigits = mpn_get_str(digits, 10, cpy, size + 1); 00229 delete[] cpy; 00230 00231 // Convert to base thousand 00232 unsigned int ngroups = (ndigits - 1) / 3 + 1; 00233 unsigned int* groups = new unsigned int[ngroups] (); 00234 for(int i=0; i < ndigits; i++) 00235 { 00236 int tenexp = ndigits - i - 1; 00237 if(tenexp % 3 == 0) 00238 { 00239 groups[tenexp / 3] += digits[i]; 00240 } 00241 else if(tenexp % 3 == 1) 00242 { 00243 groups[tenexp / 3] += digits[i] * 10; 00244 } 00245 else 00246 { 00247 groups[tenexp / 3] += digits[i] * 100; 00248 } 00249 } 00250 delete[] digits; 00251 00252 // Write the groups 00253 bool started = false; 00254 for(int i=ngroups - 1; i >= 0; i--) 00255 { 00256 if(groups[i] == 0) 00257 { 00258 continue; 00259 } 00260 if(started) 00261 { 00262 out << "," << endl; 00263 } 00264 write_sub_thousand(out, groups[i]); 00265 if(i) 00266 { 00267 write_latin_exp(out, i - 1); 00268 } 00269 started = true; 00270 } 00271 out << endl; 00272 00273 delete[] groups; 00274 } 00275 00276 }}
Copyright © 2007-2008 Remco Bloemen.
Generated on Tue Jan 22 17:35:31 2008 for symbolism by doxygen 1.5.4