欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java语言实现权重随机算法完整实例

程序员文章站 2024-02-26 19:15:28
前言 现在app就是雨后春笋,嗖嗖的往外冒啊,有经验的、没经验的、有资历的、没资历的都想着创业,创业的90%以上都要做一个app出来,好像成了创业的标配。 做了app就...

前言

现在app就是雨后春笋,嗖嗖的往外冒啊,有经验的、没经验的、有资历的、没资历的都想着创业,创业的90%以上都要做一个app出来,好像成了创业的标配。

做了app就得推广啊,怎么推,发券送钱是最多用的被不可少的了,现在好多产品或者运营都要求能够随机出优惠券的金额,但是呢又不能过于随机,送出去的券都是钱吗,投资人的钱,是吧。

所以,在随机生成的金额中就要求,小额度的几率要大,大额度的几率要小,比如说3元的70%,5块的25%,10块的5%,这个样子的概率去生成优惠券,这个怎么办呢?

对于上述的问题,直接用我们的random.next(integer range);就不够了。因为这个伪随机不带权重,3,5,10出现的概率都是一样的。

实现思路

还是拿上述的例子,3出现的概率是70%,我们给他的权重赋值为70,5出现的概率为25%,我们给他的权重赋值为25,10出现的概率为5%,我们给他的权重赋值为5.

我们按照顺序计算出权重的加和,把当前数字出现的权重加和前的值作为其权重范围的起点值,把加和后的值作为其权重范围的终点值。

java语言实现权重随机算法完整实例

这样的话,我们就可以使用random.next(100)来做随机数,然后判断随机数落在的范围,然后映射到对应的优惠券数值即可。

java实现

package com.nggirl.test.weight.random;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.random;
public class weightrandom {
	public static void main(string[] args){
		weightrandom wr = new weightrandom();
		wr.initweight(new string[]{
			"1","2","3","4"
		}
		, new integer[]{
			100,100,200,600
		}
		);
		random r = new random();
		for (int i = 0; i < 10; i++){
			integer rv = r.nextint(wr.getmaxrandomvalue());
			system.out.println(rv);
			system.out.println(wr.getelementbyrandomvalue(rv).getkey() + " " + rv);
		}
		hashmap<string, integer> keycount = new hashmap<string, integer>();
		keycount.put("1", 0);
		keycount.put("2", 0);
		keycount.put("3", 0);
		keycount.put("4", 0);
		for (int i = 0; i < 10000; i++){
			integer rv = r.nextint(wr.getmaxrandomvalue());
			string key = wr.getelementbyrandomvalue(rv).getkey();
			keycount.put(key, keycount.get(key).intvalue()+1);
		}
		system.out.println("");
	}
	private list<weightelement> weightelements;
	public void initweight(string[] keys, integer[] weights){
		if(keys == null || weights == null || keys.length != weights.length){
			return;
		}
		weightelements = new arraylist<weightelement>();
		for (int i=0; i< keys.length; i++){
			weightelements.add(new weightelement(keys[i], weights[i]));
		}
		rangeweightelemnts();
		printrvs();
	}
	private void rangeweightelemnts(){
		if(weightelements.size() == 0){
			return;
		}
		weightelement ele0 = weightelements.get(0);
		ele0.setthresholdlow(0);
		ele0.setthresholdhigh(ele0.getweight());
		for (int i = 1; i < weightelements.size(); i++){
			weightelement curelement = weightelements.get(i);
			weightelement preelement = weightelements.get(i - 1);
			curelement.setthresholdlow(preelement.getthresholdhigh());
			curelement.setthresholdhigh(curelement.getthresholdlow() + curelement.getweight());
		}
	}
	public weightelement getelementbyrandomvalue(integer rv){
		//因为元素权重范围有序递增,所以这里可以改为二分查找
		for (weightelement e:weightelements){
			if(rv >= e.getthresholdlow() && rv < e.getthresholdhigh()){
				return e;
			}
		}
		return null;
	}
	public integer getmaxrandomvalue(){
		if(weightelements == null || weightelements.size() == 0){
			return null;
		}
		return weightelements.get(weightelements.size() - 1).getthresholdhigh();
	}
	public void printrvs(){
		for (weightelement e:weightelements){
			system.out.println(e.tostring());
		}
	}
	static class weightelement{
		/**
     * 元素标记
     */
		private string key;
		/**
     * 元素权重
     */
		private integer weight;
		/**
     * 权重对应随机数范围低线
     */
		private integer thresholdlow;
		/**
     * 权重对应随机数范围高线
     */
		private integer thresholdhigh;
		public weightelement(){
		}
		public weightelement(integer weight){
			this.key = weight.tostring();
			this.weight = weight;
		}
		public weightelement(string key, integer weight){
			this.key = key;
			this.weight = weight;
		}
		public string getkey() {
			return key;
		}
		public void setkey(string key) {
			this.key = key;
		}
		public integer getweight() {
			return weight;
		}
		public void setweight(integer weight) {
			this.weight = weight;
		}
		public integer getthresholdlow() {
			return thresholdlow;
		}
		public void setthresholdlow(integer thresholdlow) {
			this.thresholdlow = thresholdlow;
		}
		public integer getthresholdhigh() {
			return thresholdhigh;
		}
		public void setthresholdhigh(integer thresholdhigh) {
			this.thresholdhigh = thresholdhigh;
		}
		public string tostring(){
			return "key:"+this.key + " weight:" + this.weight + " low:"+this.thresholdlow+" heigh:"+this.thresholdhigh;
		}
	}
}

结果:

2 102
876
4 876

二分法的实现

public weightelement getelementbyrandomvalue(integer rv){
	if(rv < 0 || rv > getmaxrandomvalue()-1){
		return null;
	}
	//此时rv必然在0 - getmaxrandomvalue()-1范围内,
	//也就是必然能够命中某一个值
	int start = 0, end = weightelements.size() - 1;
	int index = weightelements.size()/2;
	while(true){
		if(rv < weightelements.get(index).getthresholdlow()){
			end = index - 1;
		} else if(rv >= weightelements.get(index).getthresholdhigh()){
			start = index + 1;
		} else{
			return weightelements.get(index);
		}
		index = (start + end)/2;
	}
}

下面再分享一则实例,加强对权重随机算法的理解,一次到位!

权重随机算法在抽奖,资源调度等系统中应用还是比较广泛的,一个简单的按照权重来随机的实现,权重为几个随机对象(分类)的命中的比例,权重设置越高命中越容易,之和可以不等于100;

java语言实现权重随机算法完整实例

简单实现代码如下:

import java.util.arraylist;
import java.util.list;
import java.util.random;
public class weightrandom {
	static list<weightcategory> categorys = new arraylist<weightcategory>();
	private static random random = new random();
	public static void initdata() {
		weightcategory wc1 = new weightcategory("a",60);
		weightcategory wc2 = new weightcategory("b",20);
		weightcategory wc3 = new weightcategory("c",20);
		categorys.add(wc1);
		categorys.add(wc2);
		categorys.add(wc3);
	}
	public static void main(string[] args) {
		initdata();
		integer weightsum = 0;
		for (weightcategory wc : categorys) {
			weightsum += wc.getweight();
		}
		if (weightsum <= 0) {
			system.err.println("error: weightsum=" + weightsum.tostring());
			return;
		}
		integer n = random.nextint(weightsum);
		// n in [0, weightsum) 
		integer m = 0;
		for (weightcategory wc : categorys) {
			if (m <= n && n < m + wc.getweight()) {
				system.out.println("this random category is "+wc.getcategory());
				break;
			}
			m += wc.getweight();
		}
	}
}
class weightcategory {
	private string category;
	private integer weight;
	public weightcategory() {
		super();
	}
	public weightcategory(string category, integer weight) {
		super();
		this.setcategory(category);
		this.setweight(weight);
	}
	public integer getweight() {
		return weight;
	}
	public void setweight(integer weight) {
		this.weight = weight;
	}
	public string getcategory() {
		return category;
	}
	public void setcategory(string category) {
		this.category = category;
	}
}

结果:

java语言实现权重随机算法完整实例

总结

以上就是本文关于java语言实现权重随机算法完整实例的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!