2010-05-08 67 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; } 
    } 
相關問題