Вы можете обменять некоторое пространство памяти на время расчета, если вас это интересует, используя простую и небольшую справочную таблицу.
Рассмотрим этот фрагмент кода C ++ (в более ранних версиях вашего вопроса также предлагались идеи на этом языке) в качестве примера предлагаемого мной алгоритма.
#include <iostream>
#include <array>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
#include <limits>
std::string ternary_from(int value)
{
// The idea is to elaborate three figures (in base 3) at a time
constexpr int dim = 3 * 3 * 3;
// Note the values, are "reversed"
static const std::array<std::string, dim> inner_parts {
"000", "100", "200", "010", "110", "210", "020", "120", "220",
"001", "101", "201", "011", "111", "211", "021", "121", "221",
"002", "102", "202", "012", "112", "212", "022", "122", "222"
};
static const std::array<std::string, dim> parts {
"", "1", "2", "01", "11", "21", "02", "12", "22",
"001", "101", "201", "011", "111", "211", "021", "121", "221",
"002", "102", "202", "012", "112", "212", "022", "122", "222"
};
if ( value == 0 )
return std::string{"0"};
std::string result;
// Thanks @Chux for recalling that -INT_MIN is UB
unsigned tmp = value;
if ( value < 0 )
tmp = -tmp;
// note that 'dim' = 27, so you are performing a third of the calculations
while (tmp >= dim)
{
unsigned remainder = tmp % dim;
// concatenating a string at the end is easier...
result += inner_parts[remainder];
tmp = tmp / dim;
}
result += parts[tmp];
if (value < 0)
result += '-';
// now the string needs to be reversed. e.g. 3 -> 10(3), not 01
std::reverse(result.begin(), result.end());
return result;
}
int main()
{
std::vector<int> tests {
42, -8, 0, 81, 27, -28, std::numeric_limits<int>::max(), std::numeric_limits<int>::min()
};
std::cout << " decimal ternary\n";
for (int i : tests)
{
std::cout << std::setw(12) << i << std::setw(23) << ternary_from(i) << '\n';
}
}
выводит
decimal ternary
42 1120
-8 -22
0 0
81 10000
27 1000
-28 -1001
2147483647 12112122212110202101
-2147483648 -12112122212110202102