繁体   English   中英

在 JavaScript 中生成无偏随机浮点数 [0, 1)

[英]Generating unbiased random float numbers [0, 1) in JavaScript

我发现 javascript Math.random() 生成的随机浮点数的尾数位分布是有偏差的。 最低有效位始终为 0,右边的位偶数多于奇数。

此外,该区间 [0, 1) 中的许多其他可表示浮点数也不是可能的选择。 例如,0.05954861408025609 不是 2**-52 的 integer 倍数。

有没有更好的方法来生成无偏差的浮点数?

 // Histogram for mantissa bit distribution (52 bits) function histogram(func) { var counters = []; counters.length = 52; counters.fill(0); var u = new DataView(new ArrayBuffer(8)); for (var i = 0; i < 100000; i++) { var flt = func(); u.setFloat64(0, flt, false); var bits = u.getBigUint64(0); for (var j = 0; j < 52; j++) { counters[51 - j] += Number((bits >> BigInt(j)) & 1n); } } return counters; } var hist1 = histogram(Math.random); Highcharts.chart('container', { chart: { type: 'column' }, title: { text: 'Mantissa Bit Distribution' }, xAxis: { categories: [ '51', '50', '49', '48', '47', '46', '45', '44', '43', '42', '41', '40', '39', '38', '37', '36', '35', '34', '33', '32', '31', '30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0' ], crosshair: true }, yAxis: { min: 0, title: { text: 'Frequency' } }, series: [{name: 'Bit', data: hist1}] });
 <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script> <script src="https://code.highcharts.com/modules/export-data.js"></script> <script src="https://code.highcharts.com/modules/accessibility.js"></script> <figure class="highcharts-figure"> <div id="container"></div> </figure>

好的,我终于设法根据以下链接中的各种代码实现了一个无偏见的 function:

function 产生 [0, 1) 范围内的无偏均匀分布浮点数。 在该区间内,IEEE-754 浮点格式的所有可表示数字都是可能的选择(总共 1022 * 2^52 个规范化浮点数)。

Math.random() 只能生成双精度浮点值中可能的 52 位尾数的大约 0.1%。 换句话说,生成的数字应该比 Math.random 的数字“更随机”。

function output 通过了以下统计测试:

 // ##################################################################### // Generate uniformly distributed floating point numbers in [0, 1). // All representable numbers of IEEE-754 format are possible selections. function uniform01() { // Generate a random 32-bit unsigned integer within [0, 0xffffffff] const uniform32 = function() { return (Math.random() * 2 ** 32) >>> 0; }; // sample p from geometric(2) by finding the first 1-bit // in a stream of bits generated uniformly at random and // interpret it as a power of two, 00101000000000000000. let power2 = 2, x; while ((x = uniform32()) == 0) { power2 *= 2 ** 32; } // x & -x creates a bitmask for the rightmost set bit in x. // power2 is 2 with probability 1/2, 4 with probability 1/4, // 8 with probability 1/8, and so on. power2 *= (x & -x); // scale 2^52 numbers from [1, 2) into a smaller binade, // this constructs fp number in [0, 1) as dyadic rational. return (1.0 + Math.random()) / power2; } // ##################################################################### // Histogram for mantissa bit distribution (52 bits) function histogram(func) { var counters = Array(52).fill(0); var u = new DataView(new ArrayBuffer(8)); for (var i = 0; i < 100000; i++) { var flt = func(); u.setFloat64(0, flt); var bits = u.getBigUint64(0); for (var j = 0; j < 52; j++) { counters[51 - j] += Number((bits >> BigInt(j)) & 1n); } } return counters; } //var hist1 = histogram(Math.random); var hist1 = histogram(uniform01); Highcharts.chart('container', { chart: { type: 'column' }, title: { text: 'Mantissa Bit Distribution' }, xAxis: { categories: [ '51', '50', '49', '48', '47', '46', '45', '44', '43', '42', '41', '40', '39', '38', '37', '36', '35', '34', '33', '32', '31', '30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0' ], crosshair: true }, yAxis: { min: 0, title: { text: 'Frequency' } }, series: [{name: 'Bit', data: hist1}] });
 <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script> <script src="https://code.highcharts.com/modules/export-data.js"></script> <script src="https://code.highcharts.com/modules/accessibility.js"></script> <figure class="highcharts-figure"> <div id="container"></div> </figure>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM