Создавайте числа в массиве, которые суммируются до заданной суммы
Я новичок в программировании на PHP. Таким образом, в основном, что мне нужно выполнить, создайте массив из x чисел (созданных случайным образом), значение которых добавляется к n:
Скажем, мне нужно создать 4 числа, которые составляют до 30. Мне просто нужен первый случайный набор данных. Здесь 4 и 30 являются переменными, которые будут заданы пользователем.
По существу что-то вроде
x = amount of numbers;
n = sum of all x combined;
// create x random numbers which all add up to n;
$row = array(5, 7, 10, 8) // these add up to 30
Кроме того, дубликаты не допускаются, и все числа должны быть целыми положительными.
Мне нужны значения в массиве. Я когда-то общался с ним, однако мои знания довольно ограничены. Любая помощь будет оценена.
Ответы
Ответ 1
Во-первых, это действительно крутая проблема. Я почти уверен, что мой подход даже не распространяет числа отлично, но он должен быть лучше, чем некоторые другие подходы здесь.
Я решил построить массив с самого низкого номера (и перетасовать их в конце). Это позволяет мне всегда выбирать случайный диапазон, который позволит получить допустимые результаты. Поскольку числа всегда должны увеличиваться, я решал для максимально возможного числа, что гарантирует, что действительное решение все еще существует (т.е. Если 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 );
EDIT: при больших значениях $n
вы получите множество сгруппированных значений в конце массива, так как есть хорошая вероятность, что вы получите случайное значение около максимального значения, заставляя остальных быть очень близко друг к другу. Возможное исправление состоит в том, чтобы иметь взвешенный rand, но это вне меня.
Ответ 2
Я не уверен, правильно ли я вас понял, но попробуйте следующее:
$n = 4;
$max = 30;
$array = array();
do {
$random = mt_rand(0, $max);
if (!in_array($random, $array)) {
$array[] = $random;
$n--;
}
} while (n > 0);
Ответ 3
Извините, я пропустил "без дубликатов" тоже
- Нужно зацепиться за "дедупликатор"... я помещаю его в другой question
Для генерации ряда случайных чисел с фиксированной суммой:
- сделать серию случайных чисел (наибольшей практической величины, чтобы скрыть гранулярность...)
- вычислить их сумму
- умножайте каждый последовательно по желаемому/сумме
(в основном для масштабирования случайной серии до ее нового размера)
Затем для корректировки для ошибки:
- пересчитать сумму и ее разницу
от желаемой суммы
- добавить sumdiff к случайному элементу
последовательно, если это не приводит к
отрицательный, если он делает петлю к другому
случайный элемент до штрафа.
- чтобы быть ультратонким, вместо этого добавьте или
вычесть 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; }
}
Ответ 4
Надеюсь, это поможет вам больше....
Approch-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);