背景
隔壁王老师遇到了一个问题,学校给了10元钱,需要平均分给张三,李四和王五3人。王老师犯难了。
方案1
张三说,那好办,10 / 3 = 3.33333… 王老师每个人给3.34元那不就好了吗?王老师说,不行呀! 3.34*3 = 10.02 我不是亏了。要不我每个人给3.33元可不可以。 张三坚决不同意,反手举报王老师贪污他们的0.01元。
方案2
聪明的李四说了,要不这样,你先随机打算顺序,前2位给 3.33 元,最后一位给 10 - 3.33 * 2 = 3.34 元。这样就不存在谁亏了的说法。
实现
function equallyMoney($money, $weightMap) : array
{
// 这边为了让结果比较公平 应该需要加一步随机 具体按照业务逻辑修改
$totalWeight = array_sum($weightMap); // 这里的权重为整数 如果有小数。需要用高精度加法
$res = [];
foreach ($weightMap as $key => $weight) {
$res[$key] = bcdiv(bcmul($money, $weight, 2), $totalWeight, 2);
$money = bcsub($money, $res[$key], 2);
$totalWeight = bcsub($totalWeight, $weight, 4);
}
return $res;
}
运行结果
echo json_encode(equallyMoney(10, ['张三' => 1, '李四' => 1, '王五' => 1]), JSON_UNESCAPED_UNICODE);
{"张三":"3.33","李四":"3.33","王五":"3.34"} // 共10
王五运气比较好,而且大家相差不大,于是大家散了。
方案3
第二天学校又给了王老师20元钱,要发给张三,李四,王五,赵六,孙七和周八,王老师又拿出原来的算法
运行结果
echo json_encode(equallyMoney(20, ['张三' => 3, '李四' => 3, '王五' => 3, '赵六' => 3, '孙七' => 3, '周八' => 3]), JSON_UNESCAPED_UNICODE);
{"张三":"3.33","李四":"3.33","王五":"3.33","赵六":"3.33","孙七":"3.33","周八":"3.35"} // 共20
王五不同意了,为啥我们都是3.33 周八却有 3.35他算什么√8 我不同意。王老师听了三天睡不着觉,于是又了以下算法。
实现
// 这边具体实现中加了权重字段
public static function equallyMoney($money, $weightMap) : array
{
// 这边为了让结果比较公平 应该需要加一步随机 具体按照业务逻辑修改
$totalWeight = array_sum($weightMap); // 这里的权重为整数 如果有小数。需要用高精度加法
$res = [];
foreach ($weightMap as $key => $weight) {
$res[$key] = bcdiv(bcmul($money, $weight, 2), $totalWeight, 2);
$money = bcsub($money, $res[$key], 2);
$totalWeight = bcsub($totalWeight, $weight, 4);
}
return $res;
}
运行结果
echo json_encode(equallyMoney(20, ['张三' => 3, '李四' => 3, '王五' => 3, '赵六' => 3, '孙七' => 3, '周八' => 3]), JSON_UNESCAPED_UNICODE);
{"张三":"3.33","李四":"3.33","王五":"3.33","赵六":"3.33","孙七":"3.34","周八":"3.34"} // 共20
最后大家拿到钱,看看人别,感觉不是大亏。于是就散了。
王老师终于能睡个好觉了,他发誓,再也不帮学校分钱了。