1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
#include <iostream>
#include <string>
#include <limits>
#include <locale>
using NUMB = unsigned long long;
std::string convertToEnglish(NUMB donation);
struct comma_facet : public std::numpunct<char> {
explicit comma_facet(unsigned char group) : g(group) {}
char do_thousands_sep() const override { return ','; }
std::string do_grouping() const override { return std::string(1, g); }
unsigned char g {};
};
auto set000s(std::ostream& os, unsigned char group = 3)
{
return os.imbue(std::locale(os.getloc(), new comma_facet(group)));
}
int main()
{
const NUMB donations[] {18'446'744'073'709'551'615, 0, 123'456'789, 6, 111};
set000s(std::cout);
for (auto d : donations)
std::cout << d << '\n' << convertToEnglish(d) << "\n\n";
/*
NUMB donation {};
std::cout << "Enter a number between 0 and " << std::numeric_limits<NUMB>::max() << ": ";
std::cin >> donation;
std::cout << convertToEnglish(donation) << '\n';
*/
}
std::string convertToEnglish(NUMB donation)
{
static const std::string names[] {" quintillion ", " quadrillion ", " trillion ", " billion ", " million ", " thousand ", "", " hundred "};
static const std::string singles[] {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven",
"twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
static const std::string doubles[] {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
static const NUMB divisor {[]() {NUMB i {1}; for (NUMB d = (std::numeric_limits<NUMB>::digits10 / 3) * 3; d--; i *= 10); return i; }()};
std::string result;
auto dohund = [&](auto num) {
const auto thos {num % 1000};
if (thos > 99)
result += singles[thos / 100] + names[7];
if (const auto sing {thos % 100}; sing < 20)
result += result.empty() || sing > 0 ? singles[sing] : "";
else
result += doubles[sing / 10 - 2] + (sing % 10 ? " " + singles[sing % 10] : "");
};
if (donation == 0)
return singles[0];
for (auto div = divisor, nam = (decltype(divisor)) (0); div; div /= 1000, ++nam)
if (const auto n {donation / div}; n) {
dohund(n);
result += names[nam];
donation %= div;
}
return result;
}
| |