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

如何解决PHP 上余数分布的百分比限制

一个百分比列表。数字之和为 100。

$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,$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

但是如果我将变量 $limit 更改为值 6,由于添加了余数,超出了限制:

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. 将此值添加到限制下的项目,但不超过此限制

代码:(demo)

$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,$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

有关 7.4 之前的 PHP 版本,请参阅 this demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?