吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 3654|回复: 68

[其他] JAVA概率抽奖

  [复制链接]
白云点缀的蓝 发表于 2021-6-26 12:41 | 显示全部楼层 |阅读模式

礼物奖品类

[Java] 纯文本查看 复制代码
package com;

import java.math.BigDecimal;

/**
 * 奖品类
 * @author:rex
 * @date:2014年10月20日
 * @version:1.0
 */
public class Gift {
	
	private int index;
	private String gitfId;
	private String giftName;
	private double probability;

	public Gift(int index, String gitfId, String giftName, double probability) {
		this.index = index;
		this.gitfId = gitfId;
		this.giftName = giftName;
		this.probability = probability;
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	public String getGitfId() {
		return gitfId;
	}

	public void setGitfId(String gitfId) {
		this.gitfId = gitfId;
	}

	public String getGiftName() {
		return giftName;
	}

	public void setGiftName(String giftName) {
		this.giftName = giftName;
	}

	public double getProbability() {
		return probability;
	}

	public void setProbability(double probability) {
		this.probability = probability;
	}

	@Override
	public String toString() {
		return "Gift [礼物索引=" + index + ", 礼物id=" + gitfId + ", 礼物价格=" + giftName + ", 礼物概率="
				+new BigDecimal(probability+"")  + "]";
	}

}


概率算法类
[Java] 纯文本查看 复制代码
package com;

;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Random;

 
public class Lottory {
    private Random rm = new Random();

    public class AwardConfig {
        ///probaility 为概率  0.2 即 20% 得概率  0.05  即5%的中奖概率
        private BigDecimal probaility;
        ///奖品名称
        private String name;

        public BigDecimal getProbaility() {
            return probaility;
        }

        public void setProbaility(BigDecimal probaility) {
            this.probaility = probaility;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public String reward(List<AwardConfig> giftList) {
        if (giftList == null || giftList.isEmpty()) {
            return null;
        }
        // 按照概率排序(如果不排序,下面随机数的区间需要做其他处理,否则无法己算正确的概率分布)
        Collections.sort(giftList, (o1, o2) -> {
            if (o1.getProbaility().doubleValue() > o2.getProbaility().doubleValue()) {
                return 1;
            } else if (o1.getProbaility().doubleValue() == o2.getProbaility().doubleValue()) {
                return 0;
            } else {
                return -1;
            }
        });

        BigDecimal[] probabilityList = new BigDecimal[giftList.size()];
        int index = 0;
        BigDecimal allRate = BigDecimal.valueOf(0);
        String targetNumber = "";
        for (AwardConfig gift : giftList) {
            probabilityList[index] = gift.getProbaility();
            allRate = allRate.add(gift.getProbaility());
            index++;
            if (gift.getProbaility().compareTo(BigDecimal.ONE) == 0) {
                /// 如果单个奖品概率等于1,直接中该奖品
                System.out.println("如个奖品概率等于1,直接中该奖品.");
                return gift.getName();
            }
            String proStr = gift.getProbaility().toString();
            String proStrTemp = proStr.substring(proStr.indexOf(".") + 1);
            if (proStrTemp.length() > targetNumber.length()) {
                /// 找到小数位最长的那个概率配置
                targetNumber = proStrTemp;
            }
        }
//        if (allRate.intValue() != 1) {
//            ///这里可以设置 所有奖品得概率总和必须为100%,当然也可以是其他数字,根据区间匹配。
//            System.out.println("概率相加不等于1.");
//            return null;
//        }
        BigDecimal basicNumber = null;
        if (targetNumber != null && targetNumber.equals("") == false) {
            basicNumber = BigDecimal.valueOf(Math.pow(10, targetNumber.length()));
        }
        int diceRoll = rm.nextInt(basicNumber.intValue());
        if (diceRoll < 0) {
            System.err.println("随机数字小于0.");
            return null;
        }
        BigDecimal cumulative = BigDecimal.ZERO;
        for (int i = 0; i < giftList.size(); i++) {
            AwardConfig luckGift = giftList.get(i);
            if (luckGift != null && luckGift.getProbaility().compareTo(BigDecimal.ZERO) > 0) {
                cumulative = cumulative.add(luckGift.getProbaility().multiply(basicNumber));
                ///如果随机出得数字区间落在该奖品得区间内,即中得该奖品。这块得实现可以修改,只要数字区间为奖品区间就可以。
                if (diceRoll <= cumulative.intValue()) {
                    return giftList.get(i).getName();
                }
            }
        }

        return null;
    }

}


主类
[Java] 纯文本查看 复制代码
package com;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 不同概率抽奖
 * @author:rex
 * @date:2014年10月20日
 * @version:1.0
 */
public class LotteryTest {
	public static void main(List<Gift> gifts,String GiftName,Double probability,Double SubStract) {
		
		gifts = new ArrayList<Gift>();
		// 序号==物品Id==物品名称==概率
//		GiftName="52000";
//		probability=(Double) 0.002;
		gifts.add(new Gift(1, "P1", GiftName, probability));
		gifts.add(new Gift(2, "P2", "没中",(Double)(1-probability)));
//		gifts.add(new Gift(3, "P3", "物品3", 0.4d));
//		gifts.add(new Gift(4, "P4", "物品4", 0.3d));
//		gifts.add(new Gift(5, "P5", "物品5", 0d));
//		gifts.add(new Gift(6, "P6", "物品6", -0.1d));
//		gifts.add(new Gift(7, "P7", "物品7", 0.008d));

		List<Double> orignalRates = new ArrayList<Double>(gifts.size());
		for (Gift gift : gifts) {
			double probability1 = gift.getProbability();
			if (probability1 < 0) {
				probability1 = 0;
			}
			orignalRates.add(probability1);
		}
		
		// statistics
		Map<Integer, Integer> count = new HashMap<Integer, Integer>();
		double num = 1;
		for (int i = 0; i < num; i++) {
			int orignalIndex = LotteryUtil.lottery(orignalRates);

			Integer value = count.get(orignalIndex);
			count.put(orignalIndex, value == null ? 1 : value + 1);
		}

		for (Map.Entry<Integer, Integer> entry : count.entrySet()) {
			System.out.println((gifts.get(entry.getKey()) + ", count=" + entry.getValue() + ", probability="
					+ entry.getValue() / num));
			System.out.println(gifts.get(entry.getKey()).getGiftName().equals(GiftName));
			System.out.println("----------------");
//					+ entry.getValue() / num));
		}
	}

	public static void main(String[] args) {
		main(new ArrayList<Gift>(),"52000",(Double)0.002,0.01);
	}
}


使用方法,把以上代码放入你所在项目,然后调用main,传入相关参数即可开始抽奖

评分

参与人数 6HB +5 THX +2 收起 理由
消逝的过去 + 2
后学真 + 1
风里去 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
agan8888 + 1
zxjzzh + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
pmm018 + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
POJIE1123 发表于 2021-7-9 15:28 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
pUcvSEeV58 发表于 2022-2-27 19:48 | 显示全部楼层

感谢楼主分享,我瞧瞧
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
hldcY791 发表于 2022-2-27 20:03 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
vpgPGJRwInb 发表于 2022-2-27 20:07 | 显示全部楼层

感谢楼主
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
zBZnSURhcj 发表于 2022-3-1 01:23 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
CbsFco13 发表于 2022-3-8 10:31 | 显示全部楼层

谢谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
rauiM 发表于 2022-3-14 14:28 | 显示全部楼层

谢谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
AjI9634 发表于 2022-3-14 14:29 | 显示全部楼层

威武霸气!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
YLa3 发表于 2022-3-14 14:43 | 显示全部楼层

感谢楼主
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表