Как сгенерировать случайное число между (1-100) из хеша MD5 - PullRequest
2 голосов
/ 13 июля 2020

Просто, я хочу сгенерировать случайное число от 1 до 100 из MD5 ha sh.

Я всегда буду использовать строку электронной почты в качестве аргумента.

Причина в том, что я хочу создать простой тест a / b, чтобы определить конкретный c макет электронной почты в зависимости от возвращаемого числа.

Это мое решение, но я не знаю, насколько оно точно , и, честно говоря, я не совсем уверен, знаю ли я, что делаю ..

parseInt(crypto.createHash('md5').update('example@gmail.com').digest("hex"), 16) % 10**2

52 is returned

Может ли кто-нибудь привести меня в правильном направлении и дать подробное объяснение того, что происходит? Есть способ лучше?

Спасибо.

Ответы [ 3 ]

1 голос
/ 13 июля 2020

Ваша первая часть создает MD5 ha sh:

crypto.createHash('md5').update('example@gmail.com').digest("hex")
// e820bb4aba5ad74c5a6ff1aca16641f6

Полученное md5 ha sh представляет собой шестнадцатеричное число 32 di git. parseInt(hash, 16) анализирует это как целое число. Это слишком велико для целого числа, поэтому вы получите большое число с плавающей запятой. Я не уверен, что именно происходит в этом преобразовании. Затем вы берете модуль 100, который дает значение от 0 до 99.

Было бы немного легче рассуждать, если бы вы взяли первые две цифры md5 и получили число от 0 до 255 и основали свой настройки выключены.

1 голос
/ 15 июля 2020

Number s в Javascript - это просто 64-битные числа с плавающей точкой и, следовательно, подходят только для 15 десятичных цифр. Взятие модуля значений с ~ 37 десятичными цифрами будет означать, что все младшие биты фактически равны нулю, и вы получите относительно разреженный вывод. например:

a = Array(100).fill(0)
for (i = 0; i < 10000; i++) {
  d = Math.random() * 2**128
  a[d % 100] += 1
}

обратите внимание, что Math.random() * 2**128 примерно эквивалентно генерации ha sh случайного электронного письма. это дает мне a вроде:

[
  409, 0, 0, 0, 408, 0, 0, 0, 408, 0, 0, 0,
  398, 0, 0, 0, 420, 0, 0, 0, 434, 0, 0, 0,
  356, 0, 0, 0, 401, 0, 0, 0, 398, 0, 0, 0,
  423, 0, 0, 0, 346, 0, 0, 0, 397, 0, 0, 0,
  406, 0, 0, 0, 378, 0, 0, 0, 429, 0, 0, 0,
  410, 0, 0, 0, 421, 0, 0, 0, 358, 0, 0, 0,
  389, 0, 0, 0, 363, 0, 0, 0, 398, 0, 0, 0,
  398, 0, 0, 0, 426, 0, 0, 0, 396, 0, 0, 0,
  430, 0, 0, 0
]

, что означает, что возможны только значения, делящиеся на 4, и, следовательно, 75 из ваших 100 значений никогда не будут использоваться.

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

digest = crypto.createHash('md5').update('example@gmail.com').digest("hex")
Math.floor(parseInt(digest, 16) / 2**128 * 100)

вы можете использовать что-то похожее на l oop, чтобы увидеть, что это дает равномерное распределение выходных данных

обратите внимание, что оба вышеперечисленных генерируют значения от 0 до 99, поэтому вы, вероятно, захотите добавить 1 к результату

, другой способ - go с Node's BigInt введите что-то вроде:

digest = crypto.createHash('md5').update('example@gmail.com').digest()
Number(digest.readBigUInt64BE() / (2n**64n / 100n + 1n))

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

1 голос
/ 13 июля 2020

Если вы используете библиотеку seedrandom , вы можете заполнить генератор чисел. Заполнение генератора чисел гарантирует, что числа всегда будут генерироваться в одном и том же порядке при запуске "с нуля". Он отлично подходит для автоматически сгенерированных лабиринтов и игровых уровней (Think level seed в minecraft).

Используя эту библиотеку, вы можете сделать что-то вроде следующего, чтобы получить стабильные результаты.

var myrng = new Math.seedrandom('example@example.com');
console.log("int 1: " + myrng.int32());
console.log("int 2: " + myrng.int32());
console.log("int 3: " + myrng.int32());
console.log("int 4: " + myrng.int32());
console.log('round 2, repeating the above with same seed');
myrng = new Math.seedrandom('example@example.com');
console.log("int 1: " + myrng.int32());
console.log("int 2: " + myrng.int32());
console.log("int 3: " + myrng.int32());
console.log("int 4: " + myrng.int32());
console.log('round 3, repeating the above with a different seed');
myrng = new Math.seedrandom('#example@example.com');
console.log("int 1: " + myrng.int32());
console.log("int 2: " + myrng.int32());
console.log("int 3: " + myrng.int32());
console.log("int 4: " + myrng.int32());
<script src="//cdnjs.cloudflare.com/ajax/libs/seedrandom/3.0.5/seedrandom.min.js">
</script>
...