#java #algorithm #random #numbers
Вопрос:
Я хотел бы реализовать логику, основанную на предоставленной строке, я должен сгенерировать два случайных числа от 1 до 10.
У меня есть строка, подобная Johnsen, используя ее, я должен сгенерировать два числа, например 1 и 3, и в следующий раз с той же строкой она должна дать те же числа для той же строки.
Нужна помощь в разработке этого алгоритма или логики.
Комментарии:
1. Если он выдает одни и те же значения из одной и той же строки, это не случайно.
2. Похоже, то, что вам действительно нужно, — это хэш .
Ответ №1:
Java поддерживает генератор случайных чисел с помощью java.util.Random
класса. Этот класс «работает», имея начальное значение, а затем предоставляя вам некоторые случайные данные на основе этого начального значения, которое затем обновляет начальное значение до чего-то нового.
Это прагматически означает:
- 2 экземпляра j.u.Random с одинаковым начальным значением будут выдавать одинаковую последовательность значений, если вы вызовете одну и ту же последовательность вызовов для получения случайных данных.
- Но начальные значения имеют тип
long
данных-64 бита. - Таким образом, чтобы сделать то, что вы хотите, вам нужно написать алгоритм, который превращает любую строку в a
long
. - Учитывая такую длину, вы просто создаете экземпляр
j.u.Random
с такой длиной в качестве начального значения, используяnew Random(seedValue)
конструктор.
Итак, остается только один вопрос: как мне превратить строку в длинную?
Простой способ
Самый простой ответ- hashCode()
призвать их. Но, обратите внимание, хэш-коды содержат только 32 бита информации (это int
не long
так), поэтому это не охватывает все возможные начальные значения. Это вряд ли будет иметь значение, если вы не делаете это в криптографических целях. Если ДА, то вам нужно прекратить то, что вы делаете, и провести гораздо больше исследований, потому что очень легко все испортить и иметь рабочий код, который, кажется, хорошо тестируется, но который легко взломать. Ты этого не хочешь. Для начала, вы бы хотели SecureRandom
вместо этого, но это только верхушка айсберга.
Более трудный путь
Существуют алгоритмы хеширования, которые превращают произвольные данные в хэш-представления фиксированного размера. Алгоритм хэш-кода строки [A] содержит только 32-битный хэш, а [B] не является криптографически безопасным: если вы поручите мне создать строку, которая хэширует заданное значение, я могу сделать это тривиально; криптографически безопасный хэш обладает свойством, что я не могу просто приготовить вам строку, которая хэширует желаемое значение.
Вы можете искать в Интернете строки хэширования или массивы байтов (вы можете превратить строку в одно целое с str.getBytes(StandardCharsets.UTF_8)
помощью ).
Вы также можете довольно легко «свернуть» массив байтов, содержащий хэш, в длинный — просто возьмите любые 8 байтов в этом хэше и используйте их для построения длинного. «Превратите 8 байт в длинный» также содержит множество учебных пособий, если вы поищете их в Интернете.
Однако я предполагаю, что простой способ достаточно хорош для этого упражнения.
Таким образом:
String key = ...;
Random rnd = new Random(key.hashCode());
int number1 = rnd.nextInt(10) 1;
int number2 = rnd.nextInt(10) 1;
System.out.println("First number: " number1);
System.out.println("Second number: " number2);
Комментарии:
1. Если вам нужен хэш определенного размера и не требуется безопасность криптографического уровня, то хэш FNV прост в кодировании и поставляется в разных размерах.
Ответ №2:
Вы можете получить хэш-код строки, а затем использовать его для заполнения генератора случайных чисел. Используйте RNG, чтобы получить числа в диапазоне от 1 до 10.
Комментарии:
1. Или просто возьмите последние 2 цифры хэш-кода (и добавьте по 1 к каждой).
2. @Оливье Да, это сработает. Для этой цели они должны быть такими же «случайными», как и первые два результата ГСЧ.