在范围内生成随机数

7
我以前做过这件事,但现在我再次遇到困难,我认为我没有理解问题的数学基础。
我想在靠近1的小范围内设置一个随机数。例如:0.98、1.02、0.94、1.1等。所有我找到的例子都是获取在0到100之间的随机数,但是我如何使用它来获得我想要的范围呢?
编程语言并不重要,尽管我正在使用Pure Data。是否有人可以解释一下所涉及的数学?

12
你想要什么类型的分布?并且多接近1才算足够接近? - Kevin
3
你的随机数范围是多少?是从0.0到2.0吗? - Jordan Ryan Moore
15个回答

15

均匀分布

如果你想要在0.9和1.1之间进行(准)均匀分布(等距分布),则可以使用以下方法:

  range = 0.2
  return 1-range/2+rand(100)*range/100

根据需要调整范围。

伪正态分布

如果您想要一个正态分布(钟形曲线),则需要特殊的代码,这将取决于语言/库。您可以使用此代码获得接近的近似值:

sd = 0.1
mean = 1
count = 10
sum = 0
for(int i=1; i<count; i++) 
  sum=sum+(rand(100)-50)
}
normal = sum / count
normal = normal*sd + mean

统一吗?p(0.9) != p(0.9001)。我承认这是一个非常棘手的问题,涉及到IEEE754标准。 - MSalters
公平的观点 - 但考虑到问题缺乏准确性,我怀疑这对提问者不会有影响。伪均匀是否公平? :-) - Nick Fortescue
这很好,但也许应该提一下 rand 函数的参数是什么?有时标准库的随机数函数会返回一个 0 到 1 的浮点数,这取决于编程语言 - rand(100) 是一种非常基础的写法... - jheriko

10

一般而言,要在一个范围内获取一个随机数,你不会得到一个介于 0100 之间的数,而是得到一个介于 01 之间的数。然而,这并不重要,因为你可以通过将您的 # 除以 100 来获得 0-1 的数字 - 所以我不会赘述这一点。

在思考这个伪代码时,你需要将你获得的介于 01 之间的数字视为一个 百分比。换句话说,如果我有一个任意的范围介于 ab 之间,则我随机选择的点处于两端点之间的位置是多少的百分比。(因此,随机结果为0.52意味着它位于ab之间距离的52%

有了这个想法,可以这样解决问题:

  1. 设置范围的起点和终点。

    var min = 0.9;

    var max = 1.1;

  2. 获取介于01之间的随机数

    var random = Math.random();

  3. 计算范围的差值(b - a

    var range = max - min;

  4. 将你的随机数与差值相乘

    var adjustment = range * random;

  5. 再加上您的最小值。

    var result = min + adjustment;

这样,您可以逐步理解每个步骤的值:

var min = 0.9;
var max = 1.1;
var random = Math.random();      // random     == 0.52796 (for example)
var range = max - min;           // range      == 0.2
var adjustment = range * random; // adjustment == 0.105592
var result = min + adjustment;   // result     == 1.005592

请注意,结果保证在您的范围内。最小随机值为0,最大随机值为1。在这两种情况下,会出现以下情况:

var min = 0.9;
var max = 1.1;
var random = Math.random();      // random     == 0.0 (minimum)
var range = max - min;           // range      == 0.2
var adjustment = range * random; // adjustment == 0.0
var result = min + adjustment;   // result     == 0.9 (the range minimum)

var min = 0.9;
var max = 1.1;
var random = Math.random();      // random     == 1.0 (maximum)
var range = max - min;           // range      == 0.2
var adjustment = range * random; // adjustment == 0.2
var result = min + adjustment;   // result     == 1.1 (the range maximum)

6
return 0.9 + rand(100) / 500.0

或者我有什么遗漏吗?

3

Box-Müller来拯救。

var z2_cached;
function normal_random(mean, variance) {

    if ( z2_cached ) {
            var z2 = z2_cached;
            z2_cached = 0
            return z2 * Math.sqrt(variance) + mean;
    }

    var x1 = Math.random();
    var x2 = Math.random();

    var z1 = Math.sqrt(-2 * Math.log(x1) ) * Math.cos( 2*Math.PI * x2);
    var z2 = Math.sqrt(-2 * Math.log(x1) ) * Math.sin( 2*Math.PI * x2);

    z2_cached = z2;
    return z1 * Math.sqrt(variance) + mean;
}

使用均值为1,方差例如0.01的值。
for ( var i=0; i < 20; i++ ) console.log( normal_random(1, 0.01) );
0.937240893365304
1.072511121460833
0.9950053748909895
1.0034139439164074
1.2319710866884104
0.9834737343090275
1.0363970887198277
0.8706648577217094
1.0882382154101415
1.0425139197341595
0.9438723605883214
0.935894021237943
1.0846400276817076
1.0428213927823682
1.020602499547105
0.9547701472093025
1.2598174560413493
1.0086997644531541
0.8711594789918106
0.9669499056660755

该函数以给定方差为中心提供大致正态分布。


3
如果rand()返回一个在0到100之间的随机数,你需要做的就是:
(rand() / 100) * 2

获取0到2之间的随机数。

如果您想要0.9到1.1的范围,请使用以下代码:

0.9 + ((rand() / 100) * 0.2)

3
您可以通过改变变量从[0,1)范围内的均匀分布构造任何分布。特别是,如果您想要具有累积分布函数F的某个分布的随机数,则只需将来自[0,1)的均匀随机数替换为所需CDF的反函数。

一个特殊(也许是最受欢迎的)案例是正态分布N(0,1)。在这里,您可以使用Box-Muller变换。将其与标准差比例相乘并添加平均值,即可获得所需参数的正态分布。

您可以对均匀随机数进行求和,并获得正态分布的一些近似值,这种情况由上面的Nick Fortescue考虑。

如果您的源随机数是整数,则应首先构造具有某个已知分布的实域中的随机数。例如,在[0,1)中的均匀分布可以以这种方式构建。您可以获得介于0到99之间的第一个整数,将其乘以0.01,获取第二个整数,将其乘以0.0001并添加到第一个整数中,依此类推。这样,您就可以获得一个数字0.XXYYZZ...双精度约为16个小数位,因此您需要8个整数随机数来构造双倍均匀分布。


2

low + (random() / 100) * range

这段代码涉及到IT技术。例如:

0.90 + (random() / 100) * 0.2

请注意,保留html标签,但不要写解释。

2
多近?您可以使用平均值为1,标准差较小的高斯分布(又称正态分布)
如果您希望接近1的数字比稍微远离1的数字更频繁地出现,则高斯分布是合适的。
一些语言(例如Java)将在标准库中支持高斯分布。

1
你想要从rand()表达式中获得-1到1的范围作为输出。
( rand(2) - 1 )

然后根据需要将该-1到1范围进行缩放。例如,对于任一侧的.1变化:

(( rand(2) - 1 ) / 10 )

然后只需添加一个。

(( rand(2) - 1 ) / 10 ) + 1

1

除以100再加1。(我猜您是想要一个从0到2的范围?)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接