Php 金字塔型分布的调整函数
在中,我获得了编写PHP函数的帮助,该函数提供了类似金字塔的分布:Php 金字塔型分布的调整函数,php,function,random,numbers,distribution,Php,Function,Random,Numbers,Distribution,在中,我获得了编写PHP函数的帮助,该函数提供了类似金字塔的分布: function getRandomStrength($min, $max) { $ln_low = log($min, M_E); $ln_high = log($max, M_E); $scale = $ln_high-$ln_low; $rand = (mt_rand()/mt_getrandmax())*$scale+$ln_low; $value = round(pow(M_E,
function getRandomStrength($min, $max) {
$ln_low = log($min, M_E);
$ln_high = log($max, M_E);
$scale = $ln_high-$ln_low;
$rand = (mt_rand()/mt_getrandmax())*$scale+$ln_low;
$value = round(pow(M_E, $rand), 1);
return $value;
}
getRandomStrenth(1.1, 9.9);
// output could be: 1.4 or 8.3 or 9.8 or 7.2 or 2.9 or ...
当我运行50000次迭代并检查从1到9的数字出现的频率时,我得到以下列表:
- 1»26%
- 2»19%
- 3»14%
- 4»10%
- 5»9%
- 6»7%
- 7»6%
- 8»6%
- 9»4%
- 1»28%
- 2»20%
- 3»15%
- 4»11%
- 5»9%
- 6»6%
- 7»5%
- 8»5%
- 9»2%
我尝试了几件事(例如改变对数的基数),但这并没有改变任何事情。您可以对随机数使用pow
$rand=pow(mt_rand()/mt_getrandmax(),1.2)*$scale+ln_low代码>
通过使用指数值,您可以获得更小或更大的值。您可以对随机数使用pow
$rand=pow(mt_rand()/mt_getrandmax(),1.2)*$scale+ln_low代码>
通过使用指数值,您可以得到更小或更小的值。将函数的$scale
减少一小部分(常量)似乎会产生非常接近您想要的结果。通过将$scale
的减少作为从mt_rand()
随机生成的数字的函数,可以获得更精确的结果,这需要将(mt_rand()/mt_getrandmax())
保存为变量,并对$scale
执行一些额外的数学运算
以下是我的测试,您可以自己运行:
运行#2-常数=0.65
array(9) {
[1] => float(26.626) // Should be 28
[2] => float(19.464) // Should be 20
[3] => float(13.476) // Should be 15
[4] => float(10.41) // Should be 11
[5] => float(8.616) // Should be 9
[6] => float(7.198) // Should be 6
[7] => float(6.258) // Should be 5
[8] => float(5.52) // Should be 5
[9] => float(2.432) // Should be 2
}
array(9) {
[1] => float(26.75) // Should be 28
[2] => float(19.466) // Should be 20
[3] => float(13.872) // Should be 15
[4] => float(10.562) // Should be 11
[5] => float(8.466) // Should be 9
[6] => float(7.222) // Should be 6
[7] => float(6.454) // Should be 5
[8] => float(5.554) // Should be 5
[9] => float(1.654) // Should be 2
}
运行#3-常数=0.70
array(9) {
[1] => float(26.848) // Should be 28
[2] => float(19.476) // Should be 20
[3] => float(13.808) // Should be 15
[4] => float(10.764) // Should be 11
[5] => float(8.67) // Should be 9
[6] => float(7.148) // Should be 6
[7] => float(6.264) // Should be 5
[8] => float(5.576) // Should be 5
[9] => float(1.446) // Should be 2
}
将函数的$scale
减少一个小的(恒定的)量似乎会产生与您所期望的非常接近的结果。通过将$scale
的减少作为从mt_rand()
随机生成的数字的函数,可以获得更精确的结果,这需要将(mt_rand()/mt_getrandmax())
保存为变量,并对$scale
执行一些额外的数学运算
以下是我的测试,您可以自己运行:
运行#2-常数=0.65
array(9) {
[1] => float(26.626) // Should be 28
[2] => float(19.464) // Should be 20
[3] => float(13.476) // Should be 15
[4] => float(10.41) // Should be 11
[5] => float(8.616) // Should be 9
[6] => float(7.198) // Should be 6
[7] => float(6.258) // Should be 5
[8] => float(5.52) // Should be 5
[9] => float(2.432) // Should be 2
}
array(9) {
[1] => float(26.75) // Should be 28
[2] => float(19.466) // Should be 20
[3] => float(13.872) // Should be 15
[4] => float(10.562) // Should be 11
[5] => float(8.466) // Should be 9
[6] => float(7.222) // Should be 6
[7] => float(6.454) // Should be 5
[8] => float(5.554) // Should be 5
[9] => float(1.654) // Should be 2
}
运行#3-常数=0.70
array(9) {
[1] => float(26.848) // Should be 28
[2] => float(19.476) // Should be 20
[3] => float(13.808) // Should be 15
[4] => float(10.764) // Should be 11
[5] => float(8.67) // Should be 9
[6] => float(7.148) // Should be 6
[7] => float(6.264) // Should be 5
[8] => float(5.576) // Should be 5
[9] => float(1.446) // Should be 2
}
对于{0..1}中的n,y=(x^n)-1,y的范围为0到x-1。然后,通过乘以范围并除以(x-1),可以轻松地将该曲线从0映射到某个最大值。如果将值x更改为接近1的值,则曲线将接近线性,如果值较大,曲线将更像曲棍球杆,但仍会落在相同的范围内
我的初始样本值3与您所表达的并不完全相同,但您可以调整它以获得您所寻找的分布曲线
function getCustomStrength($min, $max, $x_val, $base) {
$logmax = $base-1;
$range = $max-$min;
return (pow($base,$x_val)-1)*($range/($base-1))+$min;
}
function getRandomStrength($min, $max) {
$rand = mt_rand()/mt_getrandmax();
$base = 3.0;
return getCustomStrength($min, $max, $rand, $base);
}
平均强度(1.1,9.9) 对于{0..1}中的n,y=(x^n)-1,y的范围为0到x-1。然后,通过乘以范围并除以(x-1),可以轻松地将该曲线从0映射到某个最大值。如果将值x更改为接近1的值,则曲线将接近线性,如果值较大,曲线将更像曲棍球杆,但仍会落在相同的范围内
我的初始样本值3与您所表达的并不完全相同,但您可以调整它以获得您所寻找的分布曲线
function getCustomStrength($min, $max, $x_val, $base) {
$logmax = $base-1;
$range = $max-$min;
return (pow($base,$x_val)-1)*($range/($base-1))+$min;
}
function getRandomStrength($min, $max) {
$rand = mt_rand()/mt_getrandmax();
$base = 3.0;
return getCustomStrength($min, $max, $rand, $base);
}
平均强度(1.1,9.9) 问题是结果值必须在给定范围内(在参数$min和$max之间)。一个函数不能使用另一个函数,不同于ln()?因为mt_rand()/mt_getrandmax()
在0和1之间,pow(mt_rand()/mt_getrandmax(),x)
和任何x都在0和1之间。因此,$rand将有完全相同的范围,但有不同的分布哦,是的,你是对的,当然:D答案如此简短,但太好了!这正是我需要的。但有一件事是惊人的:如果我计算从1.1到9.9的所有值的相对频率,我可以看到1.1的频率比1.2的频率低。为什么会这样?1.1应该更频繁,因为它更小,对吗?这不是一件随审判而变化的随机事件。这是一个很大的区别。我得到了这些值:1.1»6.14%,1.2»7.1%,1.3»5.08%。原因很简单,你正在使用轮来创造你的价值。但圆的分布不正确。让我们举一个简单的例子:如果我在0和2之间取一个随机数,圆将产生这样的值:0 ->0.49999=0,0.5 ->1.49999=1,1.5 ->2=2。然后,0的分布为25%,1的分布为50%,2的分布为25%。您的代码遇到了这个问题当然,这就是原因。对我来说应该是显而易见的!非常感谢您的解释、精彩的评论和简单但很好的答案。问题是结果值必须在给定范围内(在参数$min和$max之间)。一个函数不能使用另一个函数,不同于ln()?因为mt_rand()/mt_getrandmax()
在0和1之间,pow(mt_rand()/mt_getrandmax(),x)
和任何x都在0和1之间。因此,$rand将有完全相同的范围,但有不同的分布哦,是的,你是对的,当然:D答案如此简短,但太好了!这正是我需要的。但有一件事是惊人的:如果我计算从1.1到9.9的所有值的相对频率,我可以看到1.1的频率比1.2的频率低。为什么会这样?1.1应该更频繁,因为它更小,对吗?这不是一件随审判而变化的随机事件。这是一个很大的区别。我得到了这些值:1.1»6.14%,1.2»7.1%,1.3»5.08%。原因很简单,你正在使用轮来创造你的价值。但是鲁恩