文档章节

PHP 金额均衡分配算法

C
 Coco老爸
发布于 2014/09/25 13:29
字数 1030
阅读 128
收藏 0
$Money = array(
    1,2,3,3,4,4,5,5,6,6,7,7,8,8,9,10
);

$Res = AccordingToMPA($Money, array(
		'1'=>'Admin','2'=>'张三','3'=>'庆庆','4'=>'鹏鹏',
		'5'=>'Admin','6'=>'张三','7'=>'庆庆','8'=>'鹏鹏',
	));
	
print_r($Res);

/**
  *函数名称: AccordingToMPA		作者: Dandy.Mu
  *谱写日期: 2014-09-19 14:27:05
  *函数说明: 根据金额和比例进行平均分配
  *参数说明: 
			* @Param
  *返回信息: 
  */
function AccordingToMPA(Array $Amount_pool, Array $Users)
{
	if ( !is_array($Amount_pool) || !count($Amount_pool) || !is_array($Users) || !count($Users) ) return false;
	// 不改变索引情况的排序
	asort($Amount_pool);
	// 声明存储最后返回的数据的数组
	$retData = array();
	// 计算过程中用到的临时数据存放点
	$tmpData = array(
			// 待分配数据的金额的和
			'Total_amount' => array_sum($Amount_pool),
			// 待分配数据的金额总数量 是数量 不是金额的汇总
			'The_total_number_of_money' => count($Amount_pool),
			// 待分配数据的用户总数
			'The_total_number_of_users' => count($Users),
		);
	// 第一次循环的分配是先分大的还是先分小的 true 等于先分大的
	$Direction = true;
	// 人员平均金额最大限额
	$tmpData['Maximum_limit_money'] = ceil($tmpData['Total_amount'] / $tmpData['The_total_number_of_users']);
	while ($Amount_pool)
	{
		// 最大组合数
		$Combination_maximum = floor($tmpData['The_total_number_of_money'] / $tmpData['The_total_number_of_users']);
		// 判断当前这轮循环是求大还是求小
		$Larger_or_smaller = $Direction === true ? 'Large' : 'Smaller';
		// 循环所有待分配数据的用户
		foreach ($Users as $ID => $Name)
		{
			// 预期的最大值 = 人均金额 - 当前用户已经拥有的金额数
			$Expected_maximum = $tmpData['Maximum_limit_money'] - $tmpData[$ID]['Total_amount'];
			// 分析待分配数据的Key
			$tmpAmount_pool_key = Find_similar_value($Amount_pool, $Expected_maximum, $Combination_maximum, $Larger_or_smaller);
			// 这个变成false的原因多数是因为数据已经分配完了,也就是木有了啊。 有木有
			if ( $tmpAmount_pool_key === false ) break;
			// 最终的实际返回的数据
			$retData['iD'][$ID][] = $tmpAmount_pool_key;
			$retData['Money'][$ID] += $Amount_pool[$tmpAmount_pool_key];
			// Keys 当前分配人员分到的所有的Key 	【测试的时候使用】
			// Money 当前分配人员分到的所有的金额值 【测试的时候使用】
			// Total_amount 当前分配人员的总金额	【测试的时候使用】
			$tmpData[$ID]['Keys'][] = $tmpAmount_pool_key;
			$tmpData[$ID]['Money'][] = $Amount_pool[$tmpAmount_pool_key];
			$tmpData[$ID]['Total_amount'] += $Amount_pool[$tmpAmount_pool_key];
			// 清理已经赋值的
			unset($Amount_pool[$tmpAmount_pool_key]);
			// 剩余可分配的数据减1
			--$tmpData['The_total_number_of_money'];
			// 判断如果当前用户的平均金额已经满足 就将其剔除出分配组
			if ( $tmpData[$ID]['Total_amount'] >= $tmpData['Maximum_limit_money'] ) 
			{ unset($Users[$ID]); --$tmpData['The_total_number_of_users']; }
		}
		// 逆转方向
		$Direction = $Direction === true ? false : true;
	}
	unset(
			$Amount_pool, $Users, $tmpData, $Direction, $Combination_maximum, 
			$Larger_or_smaller, $Expected_maximum, $tmpAmount_pool_key
		);
	return $retData;
}
/**
  *函数名称: Find_similar_value		作者: Dandy.Mu
  *谱写日期: 2014-09-19 14:01:07
  *函数说明: 查找符合规则的数值
  *参数说明: 
			* @Amount_pool         => 数据源也就是剩余为分配的数据的数组
			* @Expected_maximum    => 预期的最大值
			* @Combination_maximum => 最大组合数,也就是当前这个人还能分配的最大的个数
			* @Larger_or_smaller   => 期待值 求大 或者 求小,[Large(求能接受的最大值)], 不等于 Large 则为求最小值
			* @Sort                => 是否进行排序,正常情况一定在外面排序好才调用,所以默认为false
  *返回信息: 符合条件的 Amount_pool 的数组的 Key
  */
function Find_similar_value(Array $Amount_pool, $Expected_maximum, $Combination_maximum, $Larger_or_smaller = 'Large', $Sort = false)
{
	if ( !is_array($Amount_pool) || !count($Amount_pool) || !is_numeric($Expected_maximum) || !is_numeric($Combination_maximum) ) return false;
	if ( $Sort === true ) asort($Amount_pool);
	// 如果是求最小值那么返回第一个就完事了
	if ( $Larger_or_smaller !== 'Large' ) { return key($Amount_pool); }
	// 如果预期的最大组合小于2那么就是1了吗 直接返回一个最大的就O了
	if ( $Combination_maximum < 2 ) { end($Amount_pool); return key($Amount_pool); }
	// 克隆一个对象用正向循环
	$Amount_pool_clone = $Amount_pool;
	// 预期的值最大值 也就是 预期值加上组合数
	$Expected_maximum_Puls_Combination = $Expected_maximum + $Combination_maximum;
	// 真实的循环次数 因为第一个循环中已经将最大的值赋值了 所以知识正向的相加最小的而已
	$Real_Combination = --$Combination_maximum;
	while ($retData = end($Amount_pool))
	{
		// 逆向循环数组那么肯定是大到小的顺序,如果当前值大于了预期最大值就跳过循环。
		if ( $retData > $Expected_maximum_Puls_Combination ) { array_pop($Amount_pool); continue; }
		reset($Amount_pool_clone);
		for ($i=0; $i < $Real_Combination; $i++)
		{ $retData += current($Amount_pool_clone); next($Amount_pool_clone); }
		// 上面计算后的值 如果小于期待的值 就证明三个数字组合的最大的数字就是当前这个了
		if ( $retData <= $Expected_maximum )
		{ 
			$retData = key($Amount_pool); 
			unset($i, $Expected_maximum, $Combination_maximum, $Amount_pool, $Larger_or_smaller, $Sort, $Amount_pool_clone, $Expected_maximum_Puls_Combination);
			return $retData;
		}
		array_pop($Amount_pool);
	}
	// 如果以上实在没有匹配就返回一个最小的
	reset($Amount_pool_clone); $retData = key($Amount_pool_clone); 
	unset($i, $Expected_maximum, $Combination_maximum, $Amount_pool, $Larger_or_smaller, $Sort, $Amount_pool_clone, $Average_Puls_Combination);
	return $retData;
}

© 著作权归作者所有

C
粉丝 1
博文 13
码字总数 6571
作品 1
深圳
私信 提问
Lvs+keepalived+nginx+php的session 保持的算法

●什么是会话保持,有什么作用 会话保持是指在负载均衡器上有一种机制,在作负载均衡的同时,还保证同一用户相关连的访问请求会被分配到同一台服务器上。 会话保持有什么作用呢,举例说明一下...

zchd
2013/06/27
0
0
nginx配置介绍

下面是Nginx配置文件的格式如下: mainevents { ....}http { .... upstream myproject { ..... } server { .... location { .... } } server { .... location { .... } } ....} nginx配置文件......

irow10
2017/03/24
0
0
超级负载均衡

超级负载均衡旨在为解决服务不断扩展、机器不断增多、机器性能差异等问题,以增强系统的稳定性,自动分配请求压力。算法实现了多个模型和均衡策略,能通过配置实现随机、轮询、一致hash等。同...

晨曦之光
2012/03/09
97
0
PHP 按百分比分配算法

分配变量固定,每一个分配变量可设置分配百分比(分配权重).所有变量百分比加起来等于100. 分配量未知.就好比LVS的负载均衡算法一样..求高手指点...

将筱云
2016/10/27
2.4K
5
说说 NGINX 的配置及优化

最近感觉很多东西在运用到一定的程度之后,会发现原来是自己了解到的不够。一方面限于实际运用到的不多,一方面可能是因为一开始没有进行全面认识。遂这里搜集整理了一番NGINX。 一、nginx启...

blackfoxya
2018/06/28
171
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot + Mybatis + Ehcache 二级缓存实例

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕...

xiaolyuh
20分钟前
4
0
Spring源码学习(二)哎呦,按菜谱做菜与AbstractAutowireCapableBeanFactory.createBean流程差不多

记得跟老婆谈恋爱时,有一天心血来潮给老婆做饭,按照菜谱一步一步的做,结果差点把厨房烧了!!! 这事至今老婆还记得。 入口 上一篇说了,AbstractBeanFactory.getBean的主流程 ,今天来说下...

温安适
22分钟前
34
0
前端UI攻城狮 你们该抛弃jQuery了

你不再需要jQuery! Web工程师太依赖jQuery了,某种意义上说jQuery已经成了JavaScript的同义词。但是我们真的需要他么?或许我们应该反思一下什么时候才真的需要jQuery。 对我个人而言开始使...

前端老手
24分钟前
5
0
六、Java设计模式之工厂方法

工厂方法定义: 定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行 类型:创建型 工厂方法-使用场景: 创建对象需要大量重复的代码 ...

东风破2019
今天
6
0
win服务器管理遇到的一系列问题记录

有些小伙伴在使用iis7远程桌面管理工具的时候总是会遇到一系列的问题,下面就是为大家介绍一下服务器日常管理过程中出现的问题及我的解决办法和心得。希望能帮到大家。   拒绝服务器重新启...

1717197346
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部