Не для какой-либо практической цели, конечно, но я попытался создать безопасное случайное число с плавающей запятой, используя модуль crypto узла. По сути, следующее:Node.js Secure Random Float from Crypto Buffer
var crypto = require('crypto');
var buf = crypto.randomBytes(4);
var float = buf.readFloatBE();
Это не работает, насколько следующее испытание может сказать, в среднем на 0,40% случаев. Вместо того, чтобы получать поплавок, я получаю NaN
.
var colors = require('colors');
var crypto = require('crypto');
var buf = new Buffer(4);
var fails = 0, tries = 100000;
var failures = [];
for (var i = 0; i < tries; i++) {
var num = crypto.randomBytes(4).readFloatBE(0);
try {
buf.writeFloatBE(num, 0);
} catch (e) {
fails++;
failures.push(buf.readUInt32BE(0).toString(2));
}
}
var percent = 100 * fails/tries;
if (fails)
percent = (percent.toFixed(2) + "%").red;
else
percent = '0.00%'.blue.bold;
console.log('Test ' + 'complete'.green.bold + ', ' + percent + ": " + fails + "/" + tries);
fails && console.log('Failed'.red + ' values:', failures.join(', '));
Я предполагаю, что это связано с IEEE одинарной точности с плавающей запятой спецификации номер, но я не знаком с точно, как поплавок хранится в двоичном виде.
Почему это происходит именно так, и, кроме простого генерирования поплавков, пока я не получу действительное число, как я могу обойти это?
EDIT: при просмотре отфильтрованных двоичных данных, похоже, что все они соответствуют одному и тому же шаблону: все первые 8 бит установлены. Все остальное случайное.
Похоже, что '0x7F800000' - бесконечность, а' 0xFF800000' - -Инфинити. '0b * 11111111', за которым следуют 23 бита, по крайней мере один, если он задан, приводит к' NaN'. – skeggse