Xnary (как двоичный, но другой), считающий - PullRequest
5 голосов
/ 10 января 2012

Я делаю функцию, которая преобразует число в строку с предопределенными символами.Оригинал, я знаю.Я начал это, потому что это казалось забавным в то время.Делать самостоятельно.Ну, это расстраивает и не весело.

Я хочу, чтобы он был похож на двоичный, так как любой левый символ стоит больше, чем его правая соседка.Двоичный код неэффективен, потому что каждый бит имеет только 1 положительное значение.Xnary эффективен, потому что «бит» никогда не бывает 0.

Набор символов (в данном случае): A - Z.

A = 1 ..
Z = 26
AA = 27 ..
AZ = 52
BA = 53 ..
BZ = 2 * 26 (B) + 26 * 1 (Z) = 78... Right?
ZZ = 26 * 26 (Z) + 26 * 1 (Z) = 702?? Right??

Я нашел this здесь , но там AA совпадает с A и AAA.Результатом функции никогда не будет AA или AAA.

Строка A отличается от AA и AAA, поэтому число также должно быть.(В отличие от двоичного 1, 01, 001 и т. Д.) И поскольку более длинная строка всегда более ценна, чем более короткая ... A < AA < AAA.

Имеет ли это смысл?Я пытался объяснить это раньше и потерпел неудачу.Я также пытался сделать это раньше.=)

Самое важное: начиная с A < AA < AAA, значение 'my' ABC выше, чем значение другого скрипта.Другое отличие: мой сценарий не существует, потому что я продолжаю терпеть неудачу.

Я пробовал с этот алгоритм :

N = 1000, Size = 3, (because 26 log(1000) = 2.x), so use 676, 26 and 1 for positions:
N = 1000
P0 = 1000 / 676 = 1.x = 1 = A
N = 1000 - 1 * 676 = 324
P1 = 324 / 26 = 12.x = 12 = L
N = 324 - 12 * 26 = 12
P1 = 12 / 1 = 12 = L
1000 => ALL

Звучит справедливо?Видимо это дерьмо.Потому что:

N = 158760, Size = 4, so use 17576, 676, 26 and 1
P0 = 158760 / 17576 = 9.x = 9 = I
N = 158760 - 9 * 17576 = 576
P1 = 576 / 676 = 0.x = 0 <<< OOPS

Если 1 равно A (самый первый из xnary), что такое 0?Невозможно, что это такое.

Так что это бюст.Другой ( на jsFiddle ) также является бюстом, потому что A != AA != AAA, и это факт.

Так чего мне не хватало на несколько долгих ночей?

О, кстати: если вам не нравятся цифры, не читайте это.

PS.Я пытался найти похожие вопросы, но ни один из них не был достаточно похожим.Одна из ссылок наиболее похожа, но «неисправна» ИМО.

Ответы [ 3 ]

4 голосов
/ 10 января 2012

Также известен как нумерация столбцов Excel. Проще сдвинуться на единицу, A = 0, ..., Z = 25, AA = 26, ..., по крайней мере, для расчетов. Для вашей схемы все, что нужно, это вычитание 1 до преобразования в Xnary соотв. дополнение после конвертации из.

Итак, с этой модификацией давайте начнем искать преобразование. Во-первых, сколько символов нам нужно для кодирования n? Ну, есть 26 однозначных чисел, 26 ^ 2 двузначных чисел, 26 ^ 3 трехзначных чисел и т. Д. Таким образом, общее количество чисел, использующих не более d цифр, составляет 26^1 + 26^2 + ... + 26^d. Это начало геометрического ряда, мы знаем замкнутую форму для суммы, 26*(26^d - 1)/(26-1). Таким образом, для кодирования n нам нужно d цифр, если

26*(26^(d-1)-1)/25 <= n < 26*(26^d-1)/25   // remember, A = 0 takes one 'digit'

или

26^(d-1) <= (25*n)/26 + 1 < 26^d

То есть нам нужно d(n) = floor(log_26(25*n/26+1)) + 1 цифр для кодирования n >= 0. Теперь мы должны вычесть общее количество чисел, которое должно содержать не более d(n) - 1 цифр, чтобы найти положение n в d(n) -значных числах, назовем это p(n) = n - 26*(26^(d(n)-1)-1)/25. И тогда кодировка n - это просто d(n) -значная кодировка base-26 p(n).

Преобразование в другом направлении - это расширение базы-26 с последующим добавлением 26*(26^(d-1) - 1)/25.

Итак, для N = 1000 мы кодируем n = 999, log_26(25*999/26+1) = log_26(961.5769...) = 2.x, нам нужно 3 цифры.

p(999) = 999 - 702 = 297
297 = 0*26^2 + 11*26 + 11
999 = ALL

Для N = 158760, n = 158759 и log_26(25*158759/26+1) = 3.66... нам нужны четыре цифры

p(158759) = 158759 - 18278 = 140481
140481 = 7*26^3 + 25*26^2 + 21*26 + 3
158759 = H        Z         V       D
2 голосов
/ 10 января 2012

Похоже, это очень стандартное «преобразование из базы 10 в базу N», где N равно 26, и вы используете буквы для представления всех цифр.

Если у вас A-Z в качестве 26-значного значения, вы можете представлять от 0 до (26 - 1) (например, двоичный код может представлять 0 - (2 - 1).

BZ = 1 * 26 + 25 * 1 = 51

Аналог будет:

19 = 1 * 10 + 9 * 1 (1 / B - первый ненулевой символ, а 9 / Z - наибольшая возможная цифра).

В принципе, у вас правильная идея, но вам нужно сместить ее так, чтобы A = 0, а не A = 1. Тогда все должно работать относительно разумно.

0 голосов
/ 22 сентября 2017

В длинном ответе @Daniel я вижу вызов log(), который является красным флажком для производительности. Вот простой способ без сложной математики:

function excelize(colNum) {
    var order = 0, sub = 0, divTmp = colNum;
    do {
        divTmp -= 26**order;
        sub += 26**order;
        divTmp = (divTmp - (divTmp % 26)) / 26;
        order++;
    } while(divTmp > 0);

    var symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
    var tr = c => symbols[symbols.indexOf(c)+10];
    Number(colNum-sub).toString(26).split('').map(c=>tr(c)).join('');
}

Пояснение:

Поскольку это не base26, нам нужно вычесть порядок базовых времен для каждого дополнительного символа («цифры»). Итак, сначала мы посчитаем порядок полученного числа и в то же время посчитаем вычитание. А затем мы конвертируем его в базу 26 и вычитаем его, а затем переводим символы в A-Z вместо 0-P.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...