日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

天天福利抽奖-JAVA概率抽奖

發布時間:2023/12/29 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 天天福利抽奖-JAVA概率抽奖 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

搞了個抽獎活動,中大獎中的簡直爽歪歪?

?

不過還是要偷偷告訴你:抽獎是有內幕的~~~(不能讓領導看到,會被打?)

總在各種app上看到轉盤抽獎,翻牌抽獎,每次抱著中最大獎的心,換來的都是未中獎的提示,可謂是竹籃打水一場空,屢戰屢敗,屢敗屢戰~

現在就聊聊中獎的事,搬好小板凳排隊做好了??♂????♂????♂?????????????

一、實現思路(這個應該不難理解吧~)


每個獎品都有對應的中獎概率,先對所有獎品中獎概率求和
計算出每個獎品在0-1之間所占的區間塊
隨機產生0-1之間的隨機數,隨機數落在哪個區間,就是中獎哪個?
例如現有以下獎品:?
獎品A 中獎概率為 0.1?
獎品B 中獎概率為 0.01?
獎品C 中獎概率為 0.001?
獎品D 中獎概率為 0.8

第一步:求出概率總和 0.1+0.01+0.001+0.8 = 0.911?
第二步:計算每個獎品的所占區間塊?
獎品A: 0.1 / 0.911 = 0.1098?
獎品B: (0.1+0.01)/ 0.911 = 0.1207?
獎品C:(0.1+0.11+0.001)/ 0.911 = 0.1218?
獎品D:(0.1+0.11+0.001+0.8)/ 0.911 = 1?
則:?
獎品A的所占區間為:0~0.1098?
獎品B的所占區間為:0.1098~0.1207?
獎品C的所占區間為:0.1207~0.1218?
獎品D的所占區間為:0.1218~1
到此為止思路應該了解了,不過我要做的是這個的升級版

根據不同類型的人分別設置概率(emm~換句話說根據身份設置概率發放獎品)

特此說明一下:里面的概率10代表10%,可以精確到小數點后兩位,比如 0.01%

二、干貨如下

import lombok.Data; import lombok.ToString; /*** @Author: yansf* @Description:獎勵實體* @Date:Creat in 10:35 AM 2019/1/16* @Modified By:*/ @Data @ToString public class RewardDto {/*** 獎品id*/private int welfareId;/*** 天天福利管理Id(Welfare_ManagerId)*/private int welfareMgrId;/*** 獎品名稱*/private String welfareName;/*** 獎品類型(游戲幣10 vip試用20 京東卡30)*/private int welfareType;/*** 獎品數量(單個獎品上限)*/private int AwardCount;/*** 獎品值*/private int welfareValue;/*** 獎品概率 (10代表10%)*/private int AwardPct;/*** 子概率-A類概率*/private int APct;/*** 子概率-B類概率*/private int BPct;/*** 子概率-C類概率*/private int CPct;/*** 子概率-D類概率*/private int DPct;/*** 獎品剩余庫存*/private int remainderAmount;/*** 獎品配置庫存*/private int totalAmount;} /*** @Author: yansf* @Description:userType 1-A類人 2-B 5-C 7-D* @Date: 11:28 AM 2019/9/5* @Modified By:*/public RewardDto lottery1(int userId, boolean isVip, int userType) {RewardDto dto = null;RewardDto dto1 = null;//獲取獎品配置信息List<RewardDto> list = welfareMapper.getRewardPctList();if (dto == null) {OptionalInt s = list.stream().filter(e -> e.getWelfareType() == 10).mapToInt(RewardDto::getWelfareValue).min();dto1 = list.stream().filter(e -> e.getWelfareValue() == s.getAsInt()).findAny().orElse(null);}//移除庫存為0的獎品list.removeIf(e -> e.getRemainderAmount() == 0);var firstReward = welfareMapper.getWelfareReceiveRecord(userId, null, null);//近一個月內是否中獎過vip試用,不再抽中vipvar vipTrial = welfareMapper.getvipTrialRecord(userId);//如果已經是vip,則不可抽vipif (isVip || vipTrial > 0) {list.removeIf(e -> e.getWelfareType() == 20);}//如果活動間第一次抽獎,中最小的獎的概率為0if (firstReward <= 0 && (list.size() >= 2)) {//移除最小獎的配置OptionalInt s = list.stream().filter(e -> e.getWelfareType() == 10).mapToInt(RewardDto::getWelfareValue).min();list.removeIf(e -> e.getWelfareValue() == s.getAsInt() && e.getWelfareType() == 10);}if (list != null && list.size() > 0) {//總的概率區間float totalPro = 0f;//存儲每個獎品新的概率區間List<Float> proSection = new ArrayList<Float>();DecimalFormat df = new DecimalFormat("######0.00");int random = -1;try {//計算總權重double sumWeight = 0;for (RewardDto award : list) {if (userType == 1) {sumWeight += award.getAPct();} else if (userType == 2) {sumWeight += award.getBPct();} else if (userType == 5) {sumWeight += award.getCPct();} else if (userType == 7) {sumWeight += award.getDPct();}}//產生隨機數double randomNumber;randomNumber = Math.random();//根據隨機數在所有獎品分布的區域并確定所抽獎品double d1 = 0;double d2 = 0;for (int i = 0; i < list.size(); i++) {if (userType == 1) {d2 += Double.parseDouble(String.valueOf(list.get(i).getAPct())) / sumWeight;if (i == 0) {d1 = 0;} else {d1 += Double.parseDouble(String.valueOf(list.get(i - 1).getAPct())) / sumWeight;}} else if (userType == 2) {d2 += Double.parseDouble(String.valueOf(list.get(i).getBPct())) / sumWeight;if (i == 0) {d1 = 0;} else {d1 += Double.parseDouble(String.valueOf(list.get(i - 1).getBPct())) / sumWeight;}} else if (userType == 5) {d2 += Double.parseDouble(String.valueOf(list.get(i).getCPct())) / sumWeight;if (i == 0) {d1 = 0;} else {d1 += Double.parseDouble(String.valueOf(list.get(i - 1).getCPct())) / sumWeight;}} else if (userType == 7) {d2 += Double.parseDouble(String.valueOf(list.get(i).getDPct())) / sumWeight;if (i == 0) {d1 = 0;} else {d1 += Double.parseDouble(String.valueOf(list.get(i - 1).getDPct())) / sumWeight;}}if (randomNumber >= d1 && randomNumber <= d2) {random = i;break;}}} catch (Exception e) {System.out.println("生成抽獎隨機數出錯,出錯原因:" + e.getMessage()); // throw e;}if (random != -1) {dto = list.get(random);}}if (dto == null) {dto = dto1;}return dto;} /*** @Author: yansf* @Description:抽獎測試* @Date: 3:35 PM 2019/8/19* @Modified By:*/@GetMapping(value = "lottery")public ResponseUtil lottery(int userId, boolean isVip, int userType) {int coin = 0;int vip = 0;int jd = 0;RewardDto result = new RewardDto();List<RewardDto> list = new ArrayList();System.out.println("抽獎開始");for (int i = 0; i < 1000; i++) {result = welfareService.lottery(userId, isVip, userType);if (result.getWelfareType() == 10) {coin += 1;} else if (result.getWelfareType() == 20) {vip += 1;} else if (result.getWelfareType() == 30) {jd += 1;}list.add(result);}Map<String, List<RewardDto>> count = list.stream().collect(Collectors.groupingBy(RewardDto::getWelfareName));if (result != null) {return ResponseUtil.response(200, "游戲幣:" + coin + ",vip:" + vip + ",京東卡:" + jd, count);} else {return ResponseUtil.response(500, "未中獎", count);}}

此處循環1000次,使用非vipD類人做一下測試,結果如下圖

概率抽獎其實很簡單,如果又要分獎品概率,又要根據不同人設置不同的概率,那就比重相乘然后相加,舉個簡單的例子:

//計算總權重double sumWeight = 0;for (RewardDto award : list) {if (userType == 1) {//此處獎品概率*不同人抽到該獎品的概率sumWeight += award.getAPct()*avard.getPct();} } for (int i = 0; i < list.size(); i++) {if (userType == 1) { //概率相乘d2 += Double.parseDouble(String.valueOf(list.get(i).getAPct()*list.get(i).getPct())) / sumWeight;if (i == 0) {d1 = 0;} else {d1 += Double.parseDouble(String.valueOf(list.get(i - 1).getAPct()*list.get(i).getPct())) / sumWeight;}}

看到這,你應該學會了吧???

(不得不diss下,多數抽獎活動大獎概率設置的很低甚至為0,大獎可謂是可望不可及,所以還是好好工作比較靠譜,寫bug,找bug,改bug? ? ???emm~)

總結

以上是生活随笔為你收集整理的天天福利抽奖-JAVA概率抽奖的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。