Last active
December 24, 2019 21:30
-
-
Save jin-x/8df799695d31dca18a5f95920f4a6b5b to your computer and use it in GitHub Desktop.
Factorial radix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <string> | |
| #include <vector> | |
| // Factorial radix | |
| namespace fact_radix | |
| { | |
| // factorial digit type | |
| using fact_digits = std::vector<int8_t>; | |
| // convert 32-bit integer number to factorial digit vector | |
| void to_fact(const int32_t n, fact_digits& result) | |
| { | |
| result.clear(); | |
| std::div_t d; | |
| d.quot = n; | |
| for (int i = 2; d.quot != 0; ++i) { | |
| d = div(d.quot, i); | |
| result.push_back(d.rem); | |
| } | |
| } // to_fact(int32_t) | |
| // convert 64-bit integer number to factorial digit vector | |
| void to_fact(const int64_t n, fact_digits& result) | |
| { | |
| result.clear(); | |
| std::lldiv_t d; | |
| d.quot = n; | |
| for (int i = 2; d.quot != 0; ++i) { | |
| d = lldiv(d.quot, i); | |
| result.push_back(d.rem); | |
| } | |
| } // to_fact(int64_t) | |
| // FAST convert 32-bit integer number to factorial digit vector | |
| void to_fact_fast(int32_t n, fact_digits& result) | |
| { | |
| result.clear(); | |
| if (n == 0) { return; } | |
| result.push_back(n % 2); n = n / 2; | |
| if (n != 0) { result.push_back(n % 3); n = n / 3; | |
| if (n != 0) { result.push_back(n % 4); n = n / 4; | |
| if (n != 0) { result.push_back(n % 5); n = n / 5; | |
| if (n != 0) { result.push_back(n % 6); n = n / 6; | |
| if (n != 0) { result.push_back(n % 7); n = n / 7; | |
| if (n != 0) { result.push_back(n % 8); n = n / 8; | |
| if (n != 0) { result.push_back(n % 9); n = n / 9; | |
| if (n != 0) { result.push_back(n % 10); n = n / 10; | |
| if (n != 0) { result.push_back(n % 11); n = n / 11; | |
| if (n != 0) { result.push_back(n % 12); n = n / 12; | |
| if (n != 0) { result.push_back(n); } | |
| }}}}}}}}}} | |
| } // to_fact_fast(int32_t) | |
| // FAST convert 64-bit integer number to factorial digit vector | |
| void to_fact_fast(int64_t n, fact_digits& result) | |
| { | |
| result.clear(); | |
| if (n == 0) { return; } | |
| result.push_back(n % 2); n = n / 2; | |
| if (n != 0) { result.push_back(n % 3); n = n / 3; | |
| if (n != 0) { result.push_back(n % 4); n = n / 4; | |
| if (n != 0) { result.push_back(n % 5); n = n / 5; | |
| if (n != 0) { result.push_back(n % 6); n = n / 6; | |
| if (n != 0) { result.push_back(n % 7); n = n / 7; | |
| if (n != 0) { result.push_back(n % 8); n = n / 8; | |
| if (n != 0) { result.push_back(n % 9); n = n / 9; | |
| if (n != 0) { result.push_back(n % 10); n = n / 10; | |
| if (n != 0) { result.push_back(n % 11); n = n / 11; | |
| if (n != 0) { result.push_back(n % 12); n = n / 12; | |
| if (n != 0) { result.push_back(n % 13); n = n / 13; | |
| if (n != 0) { result.push_back(n % 14); n = n / 14; | |
| if (n != 0) { result.push_back(n % 15); n = n / 15; | |
| if (n != 0) { result.push_back(n % 16); n = n / 16; | |
| if (n != 0) { result.push_back(n % 17); n = n / 17; | |
| if (n != 0) { result.push_back(n % 18); n = n / 18; | |
| if (n != 0) { result.push_back(n % 19); n = n / 19; | |
| if (n != 0) { result.push_back(n % 20); n = n / 20; | |
| if (n != 0) { result.push_back(n); } | |
| }}}}}}}}}}}}}}}}}} | |
| } // to_fact_fast(int64_t) | |
| // convert factorial digit vector to 64-bit integer number | |
| int64_t from_fact(const fact_digits& n) | |
| { | |
| int64_t result = 0; | |
| int64_t i = 1, fact = 1; | |
| for (const auto x : n) { | |
| result += x * fact; | |
| ++i; fact *= i; | |
| } | |
| return result; | |
| } // from_fact | |
| // convert factorial digit vector to string (digits 0..9,A..J) | |
| std::string to_str(const fact_digits& n) | |
| { | |
| if (n.empty()) { return "0"; } | |
| std::string result; | |
| if (n.back() < 0) { result.push_back('-'); } | |
| for (auto i = n.crbegin(); i != n.crend(); ++i) { | |
| int8_t x = std::abs(*i) + '0'; | |
| if (x > '9') { x += 'A'-('9'+1); } | |
| result.push_back(x); | |
| }; | |
| return result; | |
| } // to_str | |
| // convert factorial digit vector to string (decimal numbers separated by colon) | |
| std::string to_str_sep(const fact_digits& n) | |
| { | |
| if (n.empty()) { return "0"; } | |
| std::string result; | |
| if (n.back() < 0) { result.push_back('-'); } | |
| for (auto i = n.crbegin(); i != n.crend(); ++i) { | |
| result.append(std::to_string(abs(*i))); | |
| result.push_back(':'); | |
| }; | |
| result.pop_back(); | |
| return result; | |
| } // to_str_sep | |
| } // namespace fact_radix | |
| //////////////////////////////////////////////////////////////////////////////// | |
| #include <iostream> | |
| #include <chrono> | |
| using namespace std; | |
| using Clock = chrono::steady_clock; | |
| int main() | |
| { | |
| int64_t first, last; | |
| cout << "Enter value range (first and last integer numbers via space): "; | |
| cin >> first >> last; | |
| cin.ignore(); | |
| if (last < first) { | |
| cout << "First number must be less than last!" << endl; | |
| return 1; | |
| } | |
| string s; | |
| cout << "Compare fast/slow versions and check reverse conversion? (y/n) [y] : "; | |
| getline(cin, s); | |
| bool check = (tolower(s[0]) != 'n'); | |
| cout << "Show numbers? (y/n) [y] : "; | |
| getline(cin, s); | |
| bool show = (tolower(s[0]) != 'n'); | |
| int64_t total = last-first+1, to_fact_errors = 0, from_fact_errors = 0; | |
| fact_radix::fact_digits fact, fact2; | |
| Clock::time_point clock_start = Clock::now(); | |
| for (int64_t n = first; n != last+1; ++n) { | |
| fact_radix::to_fact_fast(n, fact); | |
| if (show) { | |
| cout << n << " (dec) = " << fact_radix::to_str_sep(fact) << " = " | |
| << fact_radix::to_str(fact) << " (fact)"; | |
| } | |
| if (check) { | |
| fact_radix::to_fact(n, fact2); | |
| if (fact != fact2) { | |
| ++to_fact_errors; | |
| if (show) { cout << " - to_fact_fast/to_fact ERROR !!!"; } | |
| } | |
| if (n != fact_radix::from_fact(fact)) { | |
| ++from_fact_errors; | |
| if (show) { cout << " - from_fact ERROR !!!"; } | |
| } | |
| } | |
| if (show) { cout << endl; } | |
| } | |
| Clock::time_point clock_end = Clock::now(); | |
| double elapsed_time = chrono::duration_cast<chrono::duration<double>>(clock_end - clock_start).count(); | |
| cout << "Total: " << total << " numbers"; | |
| if (check) { | |
| cout << ", to_fact_fast/to_fact errors: " << to_fact_errors | |
| << ", from_fact errors: " << from_fact_errors; | |
| } | |
| cout << endl << "Elapsed time: " << fixed << elapsed_time << " seconds" << endl; | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def to_fact_radix(n): | |
| result = "" | |
| neg = (n < 0) | |
| if neg: n = -n | |
| i = 1 | |
| while True: | |
| i += 1 | |
| result = str(n % i) + result | |
| n //= i | |
| if n == 0: break | |
| result = ":" + result | |
| if neg: result = "-" + result | |
| return result | |
| def from_fact_radix(n): | |
| neg = (n != "" and n[0] == "-") | |
| if neg: n = n[1:] | |
| lst = map(int, reversed(n.split(":"))) | |
| result = 0 | |
| f = i = 1 | |
| for d in lst: | |
| result += d * f | |
| i += 1 | |
| f *= i | |
| if neg: result = -result | |
| return result | |
| def row_fact_radix(n): | |
| neg = (n != "" and n[0] == "-") | |
| if neg: n = n[1:] | |
| lst = map(int, reversed(n.split(":"))) | |
| result = "" | |
| f = i = 1 | |
| for d in lst: | |
| if result != "": result = " + " + result | |
| result = str(d) + "*" + str(i) + "!" + result | |
| i += 1 | |
| f *= i | |
| if neg: result = "-(" + result + ")" | |
| return result | |
| for i in range(-2,121): | |
| f = to_fact_radix(i) | |
| print(f"{i} (dec) = {f} (fact) = {row_fact_radix(f)} = {from_fact_radix(f)} (dec)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment