# PHP 上余数分布的百分比限制

``````\$percent = [20.88, 14.93, 14.14, 13.29, 5.06, 4.43, 4.24, 4.22, 2.57, 2.51, 2.38, 2.18, 1.94, 1.80, 1.34, 1.21, 0.81, 0.63, 0.50, 0.48, 0.30, 0.16];
``````

``````\$limit = 8;

// Calculating the remainder of numbers exceeding \$limit.
\$rest = array_reduce(\$percent, function (\$a, \$b) use (\$limit) {
return \$limit < \$b ? \$a += (\$b - \$limit) : \$a;
});

// Number of numbers not exceeding \$limit.
\$small = array_reduce(\$percent, function (\$a, \$b) use (\$limit) {
return \$limit > \$b ? ++\$a : \$a;
});

// Percent calc with limit up to \$limit and addition of the remainder (\$rest / \$small).
array_walk(\$percent, function(&\$value) use (\$limit, \$rest, \$small) {
\$value = \$limit < \$value ? min(\$value, \$limit) : \$value + (\$rest / \$small);
});

print_r(\$percent);
print(array_sum(\$percent)) . "\n";
``````

``````Array
(
[0] => 8
[1] => 8
[2] => 8
[3] => 8
[4] => 6.7955555555556
[5] => 6.1655555555556
[6] => 5.9755555555556
[7] => 5.9555555555556
[8] => 4.3055555555556
[9] => 4.2455555555556
[10] => 4.1155555555556
[11] => 3.9155555555556
[12] => 3.6755555555556
[13] => 3.5355555555556
[14] => 3.0755555555556
[15] => 2.9455555555556
[16] => 2.5455555555556
[17] => 2.3655555555556
[18] => 2.2355555555556
[19] => 2.2155555555556
[20] => 2.0355555555556
[21] => 1.8955555555556
)
100
``````

``````Array
(
[0] => 6
[1] => 6
[2] => 6
[3] => 6
[4] => 7.24
[5] => 6.61
[6] => 6.42
[7] => 6.4
[8] => 4.75
[9] => 4.69
[10] => 4.56
[11] => 4.36
[12] => 4.12
[13] => 3.98
[14] => 3.52
[15] => 3.39
[16] => 2.99
[17] => 2.81
[18] => 2.68
[19] => 2.66
[20] => 2.48
[21] => 2.34
)
100
``````

1. 限制最大值
2. 虽然总和不是 100：
1. 计算限制下每个项目的缺失值
2. 将此值添加到限制下的项目，但不超过此限制

``````\$percent = [20.88, 14.93, 14.14, 13.29, 5.06, 4.43, 4.24, 4.22, 2.57, 2.51, 2.38, 2.18, 1.94, 1.80, 1.34, 1.21, 0.81, 0.63, 0.50, 0.48, 0.30, 0.16];

\$limit = 6;

// check if a solution is possible
if (\$limit * count(\$percent) < 100) die("Not possible");

// 1. limit the maximum value
\$limited = array_map(fn(\$value) => min(\$value, \$limit), \$percent);
// 2. while the sum is not 100
while ((\$remain = 100 - array_sum(\$limited)) > 0)
{
// get the "non-full" values
\$filtered = array_filter(\$limited, fn(\$v) => \$v < \$limit);
// get the value to add for each items
\$evenly   = \$remain / count(\$filtered);
// add the value (maximum as  possible)
\$limited  = array_map(fn(\$value) => min(\$value + \$evenly, \$limit), \$limited);
}

print_r(\$limited);
print_r(array_sum(\$limited));
``````

``````Array
(
[0] => 6
[1] => 6
[2] => 6
[3] => 6
[4] => 6
[5] => 6
[6] => 6
[7] => 6
[8] => 4.9407142857143
[9] => 4.8807142857143
[10] => 4.7507142857143
[11] => 4.5507142857143
[12] => 4.3107142857143
[13] => 4.1707142857143
[14] => 3.7107142857143
[15] => 3.5807142857143
[16] => 3.1807142857143
[17] => 3.0007142857143
[18] => 2.8707142857143
[19] => 2.8507142857143
[20] => 2.6707142857143
[21] => 2.5307142857143
)
100
``````

0 条评论