2010-05-08 65 views
15

我对PHP一般都很陌生 - 编程。所以基本上,我需要做到的是,创建X量的数字阵列(随机生成),其值加起来ñ在一个数组内创建数字,总计达到一定数量

比方说,我要创建4个数字加起来30我只需要第一个随机数据集。这里的4和30是由用户设置的变量。

本质上类似

x = amount of numbers; 
n = sum of all x's combined; 

// create x random numbers which all add up to n; 

$row = array(5, 7, 10, 8) // these add up to 30 

此外,没有允许重复和所有数字必须为正整数。

我需要数组中的值。我有时候一直在搞这个,但是,我的知识是相当有限的。任何帮助将不胜感激。

+0

是否允许重复? – Gumbo 2010-05-08 11:06:09

+0

不对,我会编辑我的帖子。 – 2010-05-08 11:07:07

+3

*(相关)* http://en.wikipedia.org/wiki/Partition_%28number_theory%29 – Gordon 2010-05-08 11:18:39

回答

7

F首先,这是一个非常酷的问题。我几乎可以肯定,我的方法甚至没有完美地分配数字,但它应该比其他一些方法更好。

我决定从最低的数字开始构建数组(最后将它们混洗)。这允许我总是选择一个随机范围,这将允许产生有效的结果。由于数字必须一直在增加,因此我解决了尽可能高的数字,以确保仍然存在有效的解决方案(即,如果n = 4且max = 31,如果第一个数字选为7,那么它不会可以挑选大于7的数字,以使4个数字的总和等于31)。

$n = 4; 
$max = 31; 
$array = array(); 

$current_min = 1; 
while($n > 1) { 
    //solve for the highest possible number that would allow for $n many random numbers 
    $current_max = floor(($max/$n) - (($n-1)/2)); 
    if($current_max < $current_min) throw new Exception("Can't use combination"); 
    $new_rand = rand($current_min, $current_max); //get a new rand 
    $max -= $new_rand; //drop the max 
    $current_min = $new_rand + 1; //bump up the new min 
    $n--; //drop the n 
    $array[] = $new_rand; //add rand to array 
} 
$array[] = $max; //we know what the last element must be 
shuffle($array); 

编辑:对于$n大值你结束了对数组的结尾了很多分组值的,因为有一个很好的机会,你会得到接近最大值迫使一个随机值休息时间非常紧密。一个可能的解决办法是有一个加权兰特,但这是超越我。

+0

THANKs队友:)我只是做了一些小的调整,它的作品就像一个魅力:) – 2010-05-09 00:49:22

+0

我想你知道这是不会产生一个完全随机的系列,否则将没有必要在最后的洗牌;) 在那里肯定有很多随机性,但是根据之前的分数和总数创建分数可能会引入倾向 - 分布中的一些 - 可能会在某些测试和应用程序中体现出来。 – strainer 2010-05-09 01:30:41

+0

@strainer正如我在“编辑”中提到的那样,当$ n值变大时,这些值似乎会在结尾附近聚集起来。这可能可以通过加权兰德来解决。这是一个非常棘手的问题,需要解决而不会出现问题。 – 2010-05-09 01:49:55

0

我不知道我是否理解正确你,但试试这个:

$n = 4; 
$max = 30; 
$array = array(); 

do { 
    $random = mt_rand(0, $max); 

    if (!in_array($random, $array)) { 
     $array[] = $random; 
     $n--; 
    } 
} while (n > 0); 
+0

我需要四个数字,它们会添加到您已使用的$ max变量中。就像我上面使用的例子:array(5,7,10,8)//这些加起来最多为30 对不起,不清楚队友。 – 2010-05-08 11:20:39

+1

这并不能保证这些数字实际上合计为30.你可以使最后一个数字是非随机的,因此它们合计为合适的数量。毕竟,它们不能都是随机的。如果这个数字已经在数组中,但你有一个小问题:) – Thorarin 2010-05-08 11:23:31

-2

希望这将帮助你更....

计算策略-1

$aRandomarray = array(); 
for($i=0;$i<100;$i++) 
{ 
    $iRandomValue = mt_rand(1000, 999); 
    if (!in_array($iRandomValue , $aRandomarray)) { 
     $aRandomarray[$i] = $iRandomValue; 
    } 
} 

Approch-2

$aRandomarray = array(); 
for($i=0;$i<100;$i++) 
{ 
    $iRandomValue = mt_rand(100, 999); 
    $sRandom .= $iRandomValue; 
} 
array_push($aRandomarray, $sRandom); 
+0

我不太确定这是如何创建n个数字来合计一个特定的数量? – 2010-05-08 11:59:22

0

对不起,我错过了“没有重复”太
- 所以需要钉在了“deduplicator” ......我把它放在其他question

产生一系列具有固定和随机数:

  • 做出一系列随机数(最大的实际量级隐藏粒度...)
  • 计算它们的总和
  • 乘法每个串联的desiredsum /总和

(basicaly比例随机系列新的大小)

再就是被舍入误差调整为:

  • 重新计算总和,并从所希望的总和
  • 其差 的sumdiff添加到随机元素 ,如果它不导致 否定,如果它循环到另一个 随机元素,直到罚款。
  • 被代替ultratight添加或 减1位随机元素 直到sumdiff = 0

从做它像这样得到的一些非随机性是当源随机量的大小过小造成粒度在结果中。

我没有PHP的,但这里有一个镜头 -

$n = ;    //size of array 
$targsum = ;  //target sum 
$ceiling = 0x3fff; //biggish number for rands 
$sizedrands = array(); 

$firstsum=0; 
$finsum=0; 

//make rands, sum size 
for($count=$n; $count>0; $count--) 
{ $arand=rand(0, $ceiling); 
    $sizedrands($count)=$arand; 
    $firstsum+=$arand; } 

//resize, sum resize 
for($count=$n; $count>0; $count--) 
{ $sizedrands($count)=($sizedrands($count)*$targsum)/$firstsum; 
    $finsum+=$sizedrands($count); 
    } 

//redistribute parts of rounding error randomly until done 
$roundup=$targsum-$finsum; 

$rounder=1; if($roundup<0){ $rounder=-1; } 

while($roundup!=0) 
{ $arand=rand(0, $n); 
    if(($rounder+$sizedrands($arand)) > 0) 
    { $sizedrands($arand)+=$rounder; 
    $roundup-=$rounder; } 
    } 
相关问题