У меня есть необходимость хранить много чисел (я могу решить, какие числа) как один уникальный номер, из которого я должен быть в состоянии получить исходный номер.
Я уже знаю 2 способа сделать это:
1) Основная теорема арифметики (простые числа)
Скажем, у меня есть 5 значений, я назначаю простое число, отличное от 1, каждому значению
a = 2
b = 3
c = 5
d = 7
e = 13
Если я хочу сохранить a, b и c, я могу умножить их 2*3*5=30
и я знаю, что никакое другое произведение простых чисел не может быть 30. Затем, чтобы проверить, содержит ли значение, например, b, все, что мне нужно сделать, это 30 % b == 0
2) Битовая маска
Так же, как разрешения Linux, используйте степени 2 и суммируйте каждое значение
Но эти 2 метода растут быстро (1-й способ быстрее 2-го), и использование простых чисел требует от меня много простых чисел.
Есть ли другой способ сделать это эффективно, когда у вас есть, например, тысяча значений?
Если вы храните, скажем, числа с базовыми 10, то выполните преобразование с помощью чисел с базовыми 11. С увеличенной базой у вас появляется дополнительная «цифра». Используйте эту цифру в качестве разделителя. Таким образом, три базовых 10 числа «10, 42, 457» становятся «10A42A457»: одно базовое число 11 (с «A» в качестве дополнительной цифры).
В какой бы базе не находились ваши исходные числа, увеличьте базу на 1 и объедините, используя дополнительную цифру в качестве разделителя. Это даст вам один номер в увеличенной базе.
Это единственное число может быть сохранено в любой удобной для вас числовой базе: например, двоичное, динарное или шестнадцатеричное.
Чтобы получить исходные числа, просто конвертируйте их в основание 11 (или что-то еще) и замените лишнюю цифру разделителями.
ETA: Вам не нужно использовать основание 11. Одно число «10A42A457» также является действительным шестнадцатеричным числом, поэтому можно использовать любое основание от 11 или выше. С Hex легче работать, чем с базой 11.
Есть ли другой способ сделать это эффективно, когда у вас есть, например, тысяча значений?
Я не математик, но это базовая математика, все зависит от дальности
Диапазон 0-1: Вы хотите хранить 4 числа 0-1 — это в основном двоичная система
Number1 + Number2 * 2^1 + Number3 * 2^2 + Number4 * 2^3
Диапазон 0-50 Вы хотите хранить 4 номера 0-49
Number1 + Number2 * 50^1 + Number3 * 50^2 + Number4 * 50^3
Диапазон 0-X Вы хотите хранить N номеров 0-X
Number1 + Number2 * (X+1)^1 + Number3 * (X+1)^2 + ... + NumberN * (X+1)^(N-1)
Если у вас нет шаблона для ваших чисел (так что он может каким-то образом сжаться), другого пути нет.
Для компьютера также очень легко определить число в отличие от простых чисел.
@FlorainK комментарий указал мне на тот факт, что я пропустил
(я могу решить, какие номера)
Единственное логичное решение — дать ваши номера ссылок
0 is 15342
1 is 6547
2 is 76234
3 is "i like stack overflow"4 is 42141
так что вы будете работать диапазон 0-4
(5 вариантов) и любой длины комбинации. Используйте ссылку при «кодировании» и «декодировании» числа
тысяча ценностей?
так что вы будете работать с диапазоном 0-999
0 is 62342
1 is 7456345653
2 is 45656234532
...
998 is 7623452
999 is 4324234326453
Допустим, вы используете 64-битную систему и язык программирования / db, который работает с 64-битными целыми числами
2^64 = 18446744073709551616
ваш максимальный диапазон 1000^X < 18446744073709551616
где X
количество номеров, которые вы можете хранить в одном 64-битном целом числе
Который только 6.
Вы можете хранить только 6 отдельных чисел 0-999, которые будут соответствовать одному 64-битному целому числу.
0,0,0,0,0,0 is 0
1,0,0,0,0,0 is 1
0,1,0,0,0,0 is 1000
999,999,999,999,999,999 is ~1e+18
Итак, вы хотите сохранить «a, b, c» или «a, b» или «a, b, c, d» или «a» и т. Д. (Спасибо @FlorianK)
в таком случае просто можно использовать побитовые операторы и степени двух
$a = 1 << 0; // 1
$b = 1 << 1; // 2
$c = 1 << 2; // 4
$d = 1 << 3; // 8
.. etc
скажем $flag
имеет $a
а также $c
$flag = $a | $c; // $flag is integer here
сейчас проверь
$ok = ($flag & $a) && ($flag & $c); // true
$ok = ($flag & $a) && ($flag & $b); // false
так что в 64-битной системе / языке / операционной системе вы можете использовать до 64 флагов, что дает вам 2 ^ 64 комбинации
другого варианта нет. простые числа намного хуже для этого, поскольку вы пропускаете много промежуточных чисел, в то время как двоичная система использует каждое отдельное число.
Я вижу, что вы используете базу данных, и вы хотите сохранить это в БД.
Я действительно думаю, что мы имеем дело с XY Проблема и вы должны пересмотреть свое заявление вместо того, чтобы делать такие обходные пути.