我今天必须解决同样的问题才能工作。我的解决方案是用 Elixir 编写的并使用递归,但我用简单的英语解释了这个想法。
以下是一些示例转换:
0 ->“A”,1 ->“B”,2 ->“C”,3 ->“D”,.. 25 ->“Z”,26 ->“AA”,27 ->“AB” , ...
乍一看,这似乎是一个普通的 26 碱基计数系统,但不幸的是,它并不是那么简单。当您意识到:
A = 0
AA = 26
这与正常的计数系统不一致,其中“0”在除该单位以外的小数位时不会表现为“1”。
要理解该算法,请考虑一个更简单但等效的 base-2 系统:
A = 0
B = 1
AA = 2
AB = 3
BA = 4
BB = 5
AAA = 6
在正常的二进制计数系统中,我们可以通过增加 2(1、2、4、8、16)的幂来确定小数位的“值”,并且二进制数的值是通过将每个数字乘以该数字的位置来计算的价值。例如 10101 = 1 * (2 ^ 4) + 0 * (2 ^ 3) + 1 * (2 ^ 2) + 0 * (2 ^ 1) + 1 * (2 ^ 0) = 21
在我们更复杂的 AB 系统中,我们可以通过检查看到小数位值是:
1, 2, 6, 14, 30, 62
该模式显示自己是(previous_unit_place_value + 1) * 2
。因此,为了获得下一个较低的单位位值,我们除以 2 并减去 1。
这可以扩展到 base-26 系统。只需除以 26 并减去 1。
现在,将普通的以 10 为基数的数字转换为特殊的以 26 为基数的公式是显而易见的。说输入是x
.
- 创建一个累加器列表
l
。
- 如果 x 小于 26,则设置
l = [x | l]
并转到步骤 5。否则,继续。
- 将 x 除以 2。取底结果为
d
,余数为r
。
- 将剩余部分作为累加器列表的头部。IE
l = [r | l]
- 以 (d - 1) 作为输入,转到第 2 步,例如
x = d - 1
- 将 """ 的所有元素转换
l
为其对应的字符。0 -> A 等。
所以,最后,这是我用 Elixir 写的答案:
defmodule BijectiveHexavigesimal do
def to_az_string(number, base \\ 26) do
number
|> to_list(base)
|> Enum.map(&to_char/1)
|> to_string()
end
def to_09_integer(string, base \\ 26) do
string
|> String.to_charlist()
|> Enum.reverse()
|> Enum.reduce({0, nil}, fn
char, {_total, nil} ->
{to_integer(char), 1}
char, {total, previous_place_value} ->
char_value = to_integer(char + 1)
place_value = previous_place_value * base
new_total = total + char_value * place_value
{new_total, place_value}
end)
|> elem(0)
end
def to_list(number, base, acc \\ []) do
if number < base do
[number | acc]
else
to_list(div(number, base) - 1, base, [rem(number, base) | acc])
end
end
defp to_char(x), do: x + 65
end
您只需将其用作BijectiveHexavigesimal.to_az_string(420)
. 它还接受可选的“基本”参数。
我知道 OP 询问了 Javascript,但我想为后代提供 Elixir 解决方案。