javascript - 在 Node.js 中的包含范围内生成大随机数

标签 javascript node.js random arbitrary-precision

所以我对老好人很熟悉

Math.floor(Math.random() * (max - min + 1)) + min;

这对小数字非常有效,但是当数字变大时,它很快就会变得有偏差,并且只返回比它低一个零的数字(例如,01e100 之间的随机数 几乎总是(每次我测试时,自从我使用 for 循环生成大量数字以来已经有数十亿次)返回 [x]e99)。是的,我等待程序生成那么多数字的时间很长,两次。至此,可以安全地假设对于所有实际用途,输出始终为 [x]e99

所以接下来我尝试了这个

Math.floor(Math.pow(max - min + 1, Math.random())) + min;

虽然这对于大范围来说非常有效,但对于小范围来说就不行了。所以我的问题是如何做到这两点 - 能够生成小随机数和大随机数而没有任何偏差(或最小偏差到不明显的程度)?

注意:我使用的是 Decimal.js处理 -1e2043 < x <1e2043 范围内的数字,但由于它是相同的算法,我在上面显示了普通的 JavaScript 形式以防止混淆。我可以采用普通答案并将其转换为 Decimal.js没有任何问题,所以请随意回答。

注释 #2:我想平均分配获得大量数字的几率。例如,1e33 应该与我的 0-1e100 示例中的 1e90 具有相同的赔率。但与此同时,我需要支持更小的数字和范围。

最佳答案

您的问题是精度。这就是您首先使用 Decimal.js 的原因。与 JS 中的所有其他 Number 一样,Math.random() 仅支持 53 位精度(某些浏览器甚至只用于创建高 32 位随机数)。但是您的值 1e100 需要 333 位精度。因此,较低的 280 位 (100 位中的小数点后约 75 位) 在您的公式中被丢弃。

但 Decimal.js 提供了一个 random() 方法。为什么不用那个?

function random(min, max){
    var delta = new Decimal(max).sub(min);
    return Decimal.random( +delta.log(10) ).mul(delta).add(min);
}

使用 e+99 得到这么多值的另一个“问题”是概率。对于 0 .. 1e100 范围,获得某些指数的概率是

e+99  => 90%, 
e+98  =>  9%,
e+97  =>  0.9%,
e+96  =>  0.09%,
e+95  =>  0.009%,
e+94  =>  0.0009%,
e+93  =>  0.00009%,
e+92  =>  0.000009%,
e+91  =>  0.0000009%,
e+90  =>  0.00000009%,
and so on

因此,如果您生成 100 亿个数字,从统计上讲,您将获得一个高达 1e+90 的值。这就是赔率。

I want to even out those odds for large numbers. 1e33 should have the same odds as 1e90 for example

好的,那么让我们在 min ... max 范围内生成 10 个随机数

function random2(min, max){
    var a = +Decimal.log10(min), 
        b = +Decimal.log10(max);
    //trying to deal with zero-values. 
    if(a === -Infinity && b === -Infinity) return 0;  //a random value between 0 and 0 ;)
    if(a === -Infinity) a = Math.min(0, b-53);
    if(b === -Infinity) b = Math.min(0, a-53);

    return Decimal.pow(10, Decimal.random(Math.abs(b-a)).mul(b-a).add(a) );
}

现在指数几乎均匀分布,但值有点倾斜。因为 101 到 101.5 10 .. 33 与 101.5 到 10 的概率相同2 34 ​​.. 100

关于javascript - 在 Node.js 中的包含范围内生成大随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45580596/

相关文章:

node.js - Node 单元测试 - TypeError : Cannot read property 'order' of undefined

php - 通过 css 和 html 随机加载壁纸

sql - T-SQL 查询在声明整数与计算查询时给出不同的结果

java - 具有随机游戏对象和难度的游戏板

javascript - 如何在函数内迭代数组对象

javascript - 为什么这个 Canvas 动画在使用 ngRoute 第二次加载时挂起?

javascript - Lodash:对对象数组进行排序,首先是字母,然后是数字

mongodb - 递增对象不起作用( mongoose、node.js、express、mongodb )

node.js - 未找到 Sequelize 关联者

javascript - 如何使用 “exec”网址而不是 “dev”网址从Google Apps脚本创建webhook。 Exec返回403错误