В поисках ответа, который работает во всех сценариях ios или для любого числа.
и
Значения могут быть в десятичном виде, например 55,55 10.10 и др. c. но в целом будет 100%
Несмотря на то, что вы ограничиваете общий вес до 100, тот факт, что вы хотите разместить десятичные значения в этом диапазоне, означает, что вы не можете предполагать, что можно выбрать максимум 100 единиц от. Если у вас гранулярность десятых долей, то каждая единица, из которой вы можете выбрать, будет .1
. Если указать до сотых долей (например, 55.55
), вам понадобится относительная базовая единица .01
за раз.
Поскольку я предпочел бы не выполнять итерацию по значениям с плавающей запятой, я рекомендую вам масштабировать увеличьте все ваши значения на коэффициент, который устраняет все числа с плавающей точкой в весе и генераторе случайных чисел - просто умножьте на 10/100/1000 все, что вам нужно, чтобы преобразовать все веса в целые числа.
Теперь выполните самую короткую работу итерационного процесса:
- L oop через ваш входной массив один раз, чтобы установить sh самую длинную десятичную точность.
- Выберите случайное целое число от 0 до ((сумма всех весов минус 1), умноженная на 10 на степень «самой длинной десятичной длины, представляющей собой»).
- L oop снова через ваш входной массив и просто проверьте, меньше ли случайное целое число чем текущий вес плюс любой предыдущий вес (ы); если нет, если это так, ломайте l oop, и поскольку выбранное взвешенное случайное число было найдено.
Код: ( Demo ) - демонстрация выполняется 10 итераций чтобы помочь выявить взвешенный эффект
$valueWeights = [
149 => 55.555,
130 => 10.0050,
131 => 5,
132 => 5.2,
133 => 10,
134 => 10.24,
135 => 5
];
$mostDecimals = 0;
// not bothering to validate against infinite and extremely fringe case floats
foreach ($valueWeights as $value => $weight) {
$tempDecimals = 0;
while ((string)$weight !== (string)floor($weight)) {
$weight *= 10; // this is not permanently mutating the weight
++$tempDecimals;
}
$mostDecimals = max($mostDecimals, $tempDecimals);
}
echo "Most Decimals: {$mostDecimals}\n";
$factor = pow(10, $mostDecimals);
echo "Factor: " , $factor , "\n";
$totalWeight = (array_sum($valueWeights) - 1) * $factor;
for ($i = 0; $i < 10; ++$i) {
$rand = mt_rand(0, $totalWeight);
echo "\nRand: " , $rand , "\n";
$cumulativeScaledWeight = 0;
foreach ($valueWeights as $value => $weight) {
$cumulativeScaledWeight += $weight * $factor;
if ($rand < $cumulativeScaledWeight) {
echo "Value: {$value}\n";
break;
}
}
}
Вывод:
Most Decimals: 3
Factor: 1000
Rand: 52197
Value: 149
Rand: 33785
Value: 149
Rand: 4783
Value: 149
Rand: 24994
Value: 149
Rand: 76588
Value: 133
Rand: 77417
Value: 133
Rand: 40541
Value: 149
Rand: 80009
Value: 133
Rand: 14826
Value: 149
Rand: 52691
Value: 149