![](/img/trans.png)
[英]Range Slider in WP8 to select a range within maximum and minimum value
[英]Random number within a range biased towards the minimum value of that range
我想生成范围(1 - 100000)内的随机数,但不是纯粹随机的,我希望结果基于一种分布。 我的意思是,总的来说,我希望数字“聚集”在范围 (1) 的最小值附近。
我已经阅读了有关 Box–Muller 变换和正态分布的信息,但我不太确定如何使用它们来实现数字生成器。
如何使用 C# 实现这样的算法?
有很多方法可以做到这一点(使用统一分布prng),我知道的很少:
组合更均匀的随机变量以获得所需的分布。
我不是数学专家,但肯定有这方面的方程式。 从随机性和统计的角度来看,这种解决方案通常具有最佳特性。 有关更多信息,请参阅著名的:
但是我们知道组合的分布数量有限。
对均匀随机变量应用非线性 function
这是最简单的实现。 您只需在<0..1>
范围内使用浮动随机数在它们上应用您的非线性 function (将分布更改为您想要的形状)(而结果仍在<0..1>
范围内)并将结果重新调整为例如,您的 integer 范围(在 C++ 中):
floor( pow( random(),5 ) * 100000 )
问题是这只是分布的盲目拟合,因此您通常需要稍微调整常量。 渲染直方图和随机图以直接查看结果质量是个好主意,如下所示:
您还可以避免过于盲目地使用 BEZIERS,如下所示:
伪随机生成器之后的分布
我知道有两种方法,更简单的是:
n
用分布后的所有值填充它
因此,只需遍历您想要的所有值 output 并计算其中有多少将在n
大小的数组中(来自您的分布)并将该数字的计数添加到数组中。 请注意,由于四舍五入,数组的填充大小可能略小于n
。 如果n
太小,您将丢失一些较少出现的数字。 因此,如果您将最不可能数的概率乘以n
它应该至少>=1
。 填充后将n
更改为实际数组大小(其中实际填充数字的数量)。
打乱数组
现在使用数组作为随机数的线性列表
因此,您只需从数组中选择一个数字并移至下一个,而不是random()
。 一旦你进入第n
个值,重新排列数组并再次从第一个开始。
该解决方案具有非常好的统计特性(精确地遵循分布),但随机特性不好,需要数组和偶尔的洗牌。 有关更多信息,请参阅:
另一个变体是避免使用数组和改组。 它是这样的:
<0..1>
范围内的随机值应用逆累积分布 function 转换为目标范围
如您所见,它就像#2 Apply non linear function...方法,但您直接使用分布而不是“一些”非线性 function。 因此,如果p(x)
是x
在<0..1>
范围内的概率,其中1
表示100%
,那么我们需要一个 function 来累积直到x
的所有概率(抱歉,不知道英语中的确切数学术语)。 对于整数:
f(x) = p(0)+p(1)+...+p(x)
现在我们需要逆 function g()
到它,所以:
y = f(x) x = g(y)
现在,如果我的 memory 对我有很好的帮助,那么这一代应该是这样的:
y = random(); // <0..1> x = g(y); // probability -> value
许多发行版都知道g()
function 但对于那些不知道(或者我们懒得推导它)的发行版,您可以在p(x)
上使用二进制搜索。 懒得写代码了,所以这里的线性搜索速度较慢:
for (x=0;x<max;x++) if (f(x)>=y) break;
所以当把所有东西放在一起(并且只使用p(x)
)时,我得到了这个(C++):
y=random(); // uniform distribution pseudo random value in range <0..1> for (f=0.0,x=0;x<max;x++) // loop x through all values { f+=p(x); // f(x) cumulative distribution function if (f>=y) break; } // here x is your pseudo random value following p(x) distribution
这种解决方案通常具有非常好的统计和随机属性,并且不需要分布是连续的 function(它甚至可以只是一个值数组)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.