src/N.Conversion.cpp

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

Hosted by SourceForge.net Logo