首页 > 其他分享 >红包分配问题

红包分配问题

时间:2023-07-11 20:00:55浏览次数:34  
标签:红包 BigDecimal int 金额 问题 luckMoney new 分配

红包分配问题

给你一个整数表示红包的总额,和另一个整数表示红包的个数

表示我们要把总金额,随机分成N个红包。

要求1:每个红包的金额都是随机的

要求2:每个人至少1分钱

 

示例代码:

 1 public class Test2 {
 2     public static void main(String[] args) {
 3         System.out.println(Arrays.toString(luckyMoney("150.01", 10)));
 4     }
 5 
 6     public static BigDecimal[] luckyMoney(String money,int n){//红包金额/元,红包个数
 7         double money1= 0;
 8         try {
 9             money1 = Double.parseDouble(money);
10         } catch (NumberFormatException e) {
11             System.out.println("输入金额错误!");
12             e.printStackTrace();
13             return null;
14         }
15         //System.out.println(money1);
16         int total=(int) (money1*100);//因为人民币的金额最小挡位为分,可以先将红包的金额转化为以分为单位,转化成整型
17         int rest=total-n;//红包剩余金额,因为每个红包的最小金额为1分,所以可以把每个红包的初始量设为1分
18         int[] luckMoney=new int[n];
19         Random r = new Random();
20         for (int i = 0; i < luckMoney.length; i++) {
21             if (i==luckMoney.length-1){//最后一个红包金额等于红包金额的最后剩余量+1分
22                 luckMoney[luckMoney.length-1]=1+rest;
23                 break;
24             }
25             if (rest>0){
26                 int temp=r.nextInt(rest+1);//
27                 luckMoney[i]=1+temp;
28                 rest-=temp;
29             }else {//红包剩余金额已经分配完了,剩余红包的金额都为1分
30                 luckMoney[i]=1;
31             }
32         }
33         BigDecimal[] luckMoney1=new BigDecimal[n];//这里用BigDecimal数组来记录红包的金额,因为BigDecimal进行计算时不会丢失精度
34         //BigDecimal sum = new BigDecimal("0");
35         for (int i = 0; i < luckMoney.length; i++) {
36             BigDecimal a = new BigDecimal(""+luckMoney[i]);
37             BigDecimal b = new BigDecimal("100");
38             luckMoney1[i]= a.divide(b,2,BigDecimal.ROUND_HALF_UP);//转化以元为单位时,除以100,应保留两位小数
39             sum=sum.add(luckMoney1[i]);
40         }
41         //System.out.println(sum);
42         return luckMoney1;
43     }
44 }

运行结果:

[16.50, 19.03, 64.12, 30.99, 8.96, 1.57, 2.10, 5.22, 0.04, 1.48]
[17.18, 112.52, 5.46, 0.97, 6.43, 3.26, 1.88, 1.27, 0.95, 0.09]
[82.38, 23.82, 14.27, 18.89, 4.31, 1.34, 4.16, 0.34, 0.12, 0.38]

这个算法虽然能达到随机分配红包金额的功能,但由上面运行结果我们不难发现,越往后红包分配的可金额越小,而且红包分配不够均匀

为了保证每个红包金额分配额度的合理,

额度应该在0.01和剩余平均值×2之间。例如:发100块钱,总共10个红包,那么平均值是10块钱一个,那么发出来的红包的额度在0.01元~20元之间波动。
当前面3个红包总共被领了40块钱时,剩下60块钱,总共7个红包,那么这7个红包的额度在:0.01~(60/7×2)=17.14之间。 修改后的代码为
 1 public class Test2 {
 2     public static void main(String[] args) {
 3         System.out.println(Arrays.toString(luckyMoney("150.01", 10)));
 4     }
 5 
 6     public static BigDecimal[] luckyMoney(String money,int n){
 7         double money1= 0;
 8         try {
 9             money1 = Double.parseDouble(money);
10         } catch (NumberFormatException e) {
11             System.out.println("输入金额错误!");
12             e.printStackTrace();
13             return null;
14         }
15         System.out.println(money1);
16         int total=(int) (money1*100);
17         int rest=total-n;
18         int restNum=n;//剩余红包个数
19         int[] luckMoney=new int[n];
20         Random r = new Random();
21         for (int i = 0; i < luckMoney.length; i++) {
22             if (i==luckMoney.length-1){
23                 luckMoney[luckMoney.length-1]=1+rest;
24                 break;
25             }
26             if (rest>0){
27                 int temp=r.nextInt(rest*2/restNum+1);//修改处
28                 restNum--;
29                 luckMoney[i]=1+temp;
30                 rest-=temp;
31             }else {
32                 luckMoney[i]=1;
33             }
34         }
35         BigDecimal[] luckMoney1=new BigDecimal[n];
36         BigDecimal sum = new BigDecimal("0");
37         for (int i = 0; i < luckMoney.length; i++) {
38             BigDecimal a = new BigDecimal(""+luckMoney[i]);
39             BigDecimal b = new BigDecimal("100");
40             luckMoney1[i]= a.divide(b,2,BigDecimal.ROUND_HALF_UP);
41             sum=sum.add(luckMoney1[i]);
42         }
43         System.out.println(sum);
44         return luckMoney1;
45     }
46 }

运行结果:

[7.21, 30.82, 26.08, 21.54, 7.81, 22.19, 9.72, 15.15, 3.89, 5.60]

在红包拆开之前,每个人,无论先后顺序,抢到的红包金额的数学期望都是一样的,如果100元分成5个红包,那么每个人抢到的金额的数学期望就是20元,但有趣的是,虽然数学期望一样,但概率密度却有很大差别。如果想详细了解红包分配的问题可以阅读这篇知乎文献:微信红包金额分配的算法是怎样的?谁比较容易到最佳手气?谁有机会拿到较大的金额? - Jingchi Wang的回答 - 知乎 https://www.zhihu.com/question/28250396/answer/86302251



标签:红包,BigDecimal,int,金额,问题,luckMoney,new,分配
From: https://www.cnblogs.com/FangwayLee/p/17545782.html

相关文章

  • django_filters/rest_framework/form.html的报错问题
    报错问题:django_filters/rest_framework/form.htm报错原因为:1没有装django_filters模块使用pip安装pipinstalldjango-filter2模块没有在配置文件中注册:将django_filters添加到installed_apps中INSTALLED_APPS=[...'django_filters',] ......
  • mybatis中数据库字段和实体类的属性映射问题
    由于数据库中表的列名一般是按照多个单词之间用下划线隔开,而java一般是驼峰命名法,所以这两者之间存在映射不到的问题,解决方案如下:1.给字段添加别名,如下:<selectid="getManagerInfo"resultType="string">selectlast_login_timelastLoginTimefromwy_manager......
  • element-ui带输入建议的input框踩坑(输入建议空白以及会闪出上一次的输入建议问题)
    element-ui带输入建议的input框踩坑(输入建议空白以及会闪出上一次的输入建议问题)原文链接:https://blog.csdn.net/wyhstars/article/details/81672195前段时间,在实现带输入建议并且支持模糊查询输入框的时候,发现了两个值得注意的小地方。整理出来,以供借鉴。废话不多说,直......
  • 【开机10】解决出现问题,你的PIN不可用,单击以重新设置PIN 无法打开相机 设置我的PIN 登
    \(弄了1.5个小时,找到这个视频,终于弄好了!!!!!!\)\(如果各位基友出现这种问题,可以参考。\)【开机10】解决出现问题,你的PIN不可用,单击以重新设置PIN无法打开相机设置我的PIN登录选项诊断启动禁用服务后问题解决......
  • 【C++学习笔记——前置声明:解决嵌套引用问题】
    在代码中,两个类相互引用的问题,那么我们就需要在头文件中相互写#include,这样会造成相互循环cpoy头文件,编译器报错,为了解决这个问题,设置了前置声明这个方法。A.h#ifndefA_H#defineA_HclassBclassA{typedefvector<string>::sizetypesize_type;B*b;}#endifB.h#if......
  • 适配器模式解决数据格式适配问题
    @RestController@RequestMapping("/ClientUserAssist/")publicclassClientUserAssistController{@AutowiredClientUserAssistMapperclientUserAssistMapper;/**子系统数据导入接口**/@Transactional(rollbackFor=Exception.class)@PostMa......
  • spark 的踩坑记录(二)spark 字符串截取问题
     前言接之前的spark踩坑记录,回想起当时折磨很久的一个问题,结果导致开发中花了很长时间才完全解决。主要原因为spark和java的字符串截取函数不一致导致的。主要技术框架背景介绍spark:2.4.3scala:2.11.12背景实际工作中会处理很多文本数据流,例如文章信息,评论信息等,调......
  • java连接mqtt总是自动断开的问题排查及解决
    问题描述最近在做一个视频监控平台,要同步下级平台的摄像头信息数据,是通过其他同事写的c++服务往mqtt里推数据,我这边通过java连接mqtt监听主题获取摄像头信息。刚开始写完都还好,但是测试过一段时间,发现javaclient连接总是会自动断开,并且还会有丢失消息的情况。一开始怀疑是网络......
  • 78.类如何实现只能静态分配和只能动态分配
    78.类如何实现只能静态分配和只能动态分配1.前者是把new、delete运算符重载为private属性。后者是把构造、析构函数设为protected属性,再用子类来动态创建2.建立类的对象有两种方式:①静态建立,例如Aa;静态建立一个类对象,就是由编译器为对象在栈空间中分配内存。使用这种方法,......
  • postgresql序列重复问题处理
    问题在执行数据插入时,postgresql提示morethanoneowned sequence found错误。这个和之前文章中写的序列编号错乱不同,是由数据表的一个列生成了多个序列导致的。(常见于两个数据库的拷贝、同步等操作)。如果查看序列,会发现序列中有很多重复的项目,可以执行语句:SELECT'DROPSE......