Подтвердить что ты не робот

Есть ли простой способ конвертировать уникальную строку символов в уникальный номер в JavaScript?

Это почти кросс-пост из Math SE, в то время как объяснение моей проблемы идентично, на Math.SE я просил математическое решение моей проблемы.

Моя проблема заключается в том, что решение, которое я получил на Math.SE, было "конвертировать в базу 35", что, вероятно, очень хороший ответ, но я действительно ужасен по математике и не понимаю, как применить решение в своем коде, Я попытался найти урок по конвертации в разные базы, и это довольно запутанно для меня. Даже глядя на вопрос о преобразовании чисел в базы в JavaScript не дал понять, как именно я буду использовать его для того, что мне нужно делать.

Есть ли простой способ справиться с этим в JavaScript? Здесь вопрос полностью:

У меня необычная проблема программирования, и ее математическая сторона меня озадачила.

Я создал уникальную строку из семи символов, каждая из которых случайным образом выбирается из этих возможностей: ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789 например A6HJ92B, и мне нужно преобразовать ее в уникальное числовое значение. При преобразовании никакие две версии этой случайной строки не могут быть номером имени.

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

Итак, моя идея состояла в том, чтобы создать таблицу, подобную этой:

A : 1,
B : 2,
C : 3,
D : 4,
E : 5,
F : 6,
G : 7,
H : 8,

... you get the idea ...

5 : 31,
6 : 32,
7 : 33,
8 : 34,
9 : 35

И тогда я бы добавил все числа вверх...

A6HJ92B:

A : 1
6 : 32
H : 8
J : 10
9 : 35
2 : 28
B : 2

1+32+8+10+35+28+2 = 116

... но я понял, что это ошибочная идея, потому что многие возможные строки будут "сталкиваться" или равны одному и тому же числу. Мне нужно, чтобы каждая уникальная строка равнялась уникальному числу.

Поэтому, даже если я умножу каждое значение символа (1*32*8*10*35*28*2 = 5,017,600), я думаю, что там могут быть и возможные столкновения.

Есть ли способ вычислить это таким образом, чтобы исключить столкновения? Если устранение конфликтов невозможно, какие методы я могу использовать для их минимизации?

4b9b3361

Ответ 1

В принципе, вы хотите преобразовать injective f : S → N, где S - это набор строк JS длиной 7 с символами A-Z1-9, а N - множество всех JS-чисел.

Возможный подход предполагает, что строки в S являются positional кодировкой чисел, как вы пытались.

Однако для того, чтобы быть инъективным (избегать столкновений), вы должны умножить значение каждого символа на основание на силу положения.

Например, учитывая следующую таблицу значений символов

0 ⟶  0
1 ⟶  1
⋮      ⋮
9 ⟶  9
A ⟶ 10
B ⟶ 11
⋮      ⋮
Z ⟶ 35

A6HJ92B станет 10×36⁶ + 6×36⁵ + 17×36⁴ + 19×36³ + 9×36² + 2×36 + 11, то есть 22160072099.

Вы легко можете преобразовать с помощью parseInt и toString:

parseInt('A6HJ92B', 36); // 22160072099
(22160072099).toString(36).toUpperCase(); // "A6HJ92B"

Если вы хотите использовать произвольную таблицу значений, вам придется закодировать преобразования вручную.

Обратите внимание, что в JS цифры являются платами с двойной точностью 64 бит. Это означает, что существует конечная точность, и вы не можете хранить произвольно большие целые числа. Он не будет работать должным образом за пределами этого максимума

Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MAX_SAFE_INTEGER.toString(36).toUpperCase(); // "2GOSA7PA2GV"

Но поскольку ваши строки имеют только 7 символов, этого должно быть достаточно.

Ответ 2

По сути, вы хотите получить эквивалент Java hashcode. Это формула, используемая в Java: String hashcode formula где n - общая сумма длина строки, а s [i] - i-й символ строки. В основном, что вы делаете:

Для каждого символа в строке умножьте его на 31, подняв до степени разности между общей длиной строки и индексом текущего символа в строке минус 1.

Ответ 3

Ты просто не думаешь о проблеме правильно. Начните с того, с чем вы более знакомы; десятичных или базовых 10 чисел.

Число 7158 состоит из:

  7 x 10 ^ 3
 +1 x 10 ^ 2
 +5 x 10 ^ 1
 +8 x 10 ^ 0

Чтобы представить число в базе X, вы замените 10 на X.

Итак, теперь вопрос заключается в том, как преобразовать базы. Самое простое решение состоит в том, чтобы разделить на X несколько раз - каждый раз преобразовывать остаток в базу X и добавлять его в начало выходной строки до тех пор, пока ничего не останется, затем используйте целую часть деления для следующей итерации:

7158 /35 = 204 remainder 18
204 / 35 = 5 remainder 29
5 / 35 = 0 remainder 5

Итак, в базе 35 десятичное число 7158 представлено символами, которые вы выбираете для [5] [29] [18]

Если вы попробуете пример выше самостоятельно, умножив дробную часть каждого деления на 35, вы можете получить некоторые результаты, которые не являются целыми числами - компьютеры работают в двоичном формате (и автоматически выполняют базовое преобразование) и работают только с фиксированным числом цифр - Т.е. в зависимости от того, как вы выполняете расчет, вам может понадобиться округлить около 0,00001, чтобы получить остаток в виде целого числа.

Ответ 4

Вы можете умножить на силу положения:

function StringAdder(obj){
  this.vals = obj;
  this.add = function(str){
    var s = str.split(''), l = s.length, p = Math.pow(10, (l-1)), r = 0;
    for(var i=0; i<l; i++){
      r += this.vals[s[i]]*p; p = p/10;
    }
    return r;
  }
}
var vals = {
  A: 1,
  6: 32,
  H: 8,
  J: 10,
  9: 35,
  2: 28,
  B: 2
}
var sa = new StringAdder(vals);
console.log(sa.add('A6HJ92B')); console.log(sa.add('HJA6B29'));