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))
, что позволяет избежать преобразования в строки и обратно, но дает в основном тот же ответ.