我想在靠近1的小范围内设置一个随机数。例如:0.98、1.02、0.94、1.1等。所有我找到的例子都是获取在0到100之间的随机数,但是我如何使用它来获得我想要的范围呢?
编程语言并不重要,尽管我正在使用Pure Data。是否有人可以解释一下所涉及的数学?
如果你想要在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
一般而言,要在一个范围内获取一个随机数,你不会得到一个介于 0
和 100
之间的数,而是得到一个介于 0
和 1
之间的数。然而,这并不重要,因为你可以通过将您的 # 除以 100
来获得 0
-1
的数字 - 所以我不会赘述这一点。
在思考这个伪代码时,你需要将你获得的介于 0
和 1
之间的数字视为一个 百分比。换句话说,如果我有一个任意的范围介于 a
和 b
之间,则我随机选择的点处于两端点之间的位置是多少的百分比。(因此,随机结果为0.52
意味着它位于a
和b
之间距离的52%
)
有了这个想法,可以这样解决问题:
设置范围的起点和终点。
var min = 0.9;
var max = 1.1;
获取介于0
和1
之间的随机数
var random = Math.random();
计算范围的差值(b
- a
)
var range = max - min;
将你的随机数与差值相乘
var adjustment = range * random;
再加上您的最小值。
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)
return 0.9 + rand(100) / 500.0
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;
}
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
该函数以给定方差为中心提供大致正态分布。
(rand() / 100) * 2
获取0到2之间的随机数。
如果您想要0.9到1.1的范围,请使用以下代码:
0.9 + ((rand() / 100) * 0.2)
一个特殊(也许是最受欢迎的)案例是正态分布N(0,1)。在这里,您可以使用Box-Muller变换。将其与标准差比例相乘并添加平均值,即可获得所需参数的正态分布。
您可以对均匀随机数进行求和,并获得正态分布的一些近似值,这种情况由上面的Nick Fortescue考虑。
如果您的源随机数是整数,则应首先构造具有某个已知分布的实域中的随机数。例如,在[0,1)中的均匀分布可以以这种方式构建。您可以获得介于0到99之间的第一个整数,将其乘以0.01,获取第二个整数,将其乘以0.0001并添加到第一个整数中,依此类推。这样,您就可以获得一个数字0.XXYYZZ...双精度约为16个小数位,因此您需要8个整数随机数来构造双倍均匀分布。
low + (random() / 100) * range
0.90 + (random() / 100) * 0.2
( rand(2) - 1 )
然后根据需要将该-1到1范围进行缩放。例如,对于任一侧的.1变化:
(( rand(2) - 1 ) / 10 )
然后只需添加一个。
(( rand(2) - 1 ) / 10 ) + 1
除以100再加1。(我猜您是想要一个从0到2的范围?)