文档章节

抢红包的问题

MethodMe
 MethodMe
发布于 2017/01/21 10:53
字数 800
阅读 1155
收藏 52

        最近比较忙,好久没写点东西了。上周公司年会,群里抢红包,突发感想,写一个抢红包的小程序玩玩吧。下面来说一下要求和思路。

         此处用例子说明:假设发10个人的随机红包,总额100元。

         要求:1、所有的人必须都能领到红包(不能说谁领到了0分)。

                  2、所有人领完之后,总额必须等于红包总额(不能领完了还剩几块钱这样的)。

         思路:1、把总额(元)换成分为单位,分计算起来比较方便。

                   2、把总分,划分人数减1个断点,这样就分成了10份。

                   3、每个人领取其中一份。

         下面可以看一下代码:        

package test;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
public class RedBag {
    public static void main(String[] args) throws Exception {
        // 此处 默认 10个人 分100元 即10000分
        ArrayList<Double> resultList = getAll(10, 100);
        //此处为验证总数  
        double sum = 0;
        for (double d : resultList) {
            sum += d;
            System.out.println(d);
        }
        System.out.println(sum);
    }

    // money 为元为单位
    public static ArrayList<Double> getAll(int peopleNum, double money) {
        /* 
         * 换成分    这里会出现精度问题
         * 
         * 使用bigDecimal 可以解决部分情况,但是最后求和那里还会出现 精度问题(当然,这个并不影响分的红包)
         * 
         * */
        BigDecimal mm = new BigDecimal(money + "");
        int total = mm.multiply(new BigDecimal(100)).intValue();
        System.out.println(total);
        // 用于返回
        ArrayList<Double> rList = new ArrayList<Double>();
        // 10个人 分9分
        HashSet<Integer> set = getRand(peopleNum - 1, total);
        // set 变数组 
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int ii : set) {
            list.add(ii);
        }
        // 排序后,两个数之间差值,就是分的钱数的分数了。
        Collections.sort(list);
        // 第一个
        rList.add(list.get(0) / 100.0);
        for (int i = 1; i < list.size(); i++) {
            rList.add((list.get(i) - list.get(i - 1)) / 100.0);
        }
        // 最后一个
        rList.add((total - list.get(list.size() - 1)) / 100.0);
        return rList;
    }
    
    //生成在 一到总分数之间的随机数字,并保证个数(虽然说随机数字重复几率不大,但是也要预防,防止出现0分情况)
    public static HashSet<Integer> getRand(int num, int times) {
        HashSet<Integer> set = new HashSet<Integer>();
        while (set.size() < num) {
            int one = (int) (Math.random() * (times - 1) + 1);
            set.add(one);
        }
        return set;
    }
}

        最后,感谢月影南溪同学,提议所有的都用分(整数来处理),所有里面的是分,确实可以省却很多处理。谢谢。同时,很开心和大家一起写程序。

        可以整理为这个。

public static void main(String[] args) throws Exception {
        // 此处 默认 10个人 分135.45元 即13545分
        ArrayList<Integer> resultList = getAll(10, 13545);
        //此处为验证总数  
        int sum = 0;
        for (Integer d : resultList) {
            sum += d;
            System.out.println(d);
        }
        System.out.println(sum);
    }

    // money 分为单位
    public static ArrayList<Integer> getAll(int peopleNum, int money) {
        // 用于返回
        ArrayList<Integer> rList = new ArrayList<Integer>();
        // 10个人 分9分
        HashSet<Integer> set = getRand(peopleNum - 1, money);
        // set 变数组 
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int ii : set) {
            list.add(ii);
        }
        // 排序后,两个数之间差值,就是分的钱数的分数了。
        Collections.sort(list);
        // 第一个
        rList.add(list.get(0));
        for (int i = 1; i < list.size(); i++) {
            rList.add(list.get(i) - list.get(i - 1));
        }
        // 最后一个
        rList.add(money - list.get(list.size() - 1));
        return rList;
    }
    
    //生成在 一到总分数之间的随机数字,并保证个数(虽然说随机数字重复几率不大,但是也要预防,防止出现0分情况)
    public static HashSet<Integer> getRand(int num, int times) {
        HashSet<Integer> set = new HashSet<Integer>();
        while (set.size() < num) {
            int one = (int) (Math.random() * (times - 1) + 1);
            set.add(one);
        }
        return set;
    }

© 著作权归作者所有

上一篇: 扫码登录
下一篇: 单账号登录初探
MethodMe
粉丝 8
博文 3
码字总数 1767
作品 0
朝阳
程序员
私信 提问
加载中

评论(8)

JackY-Ji
JackY-Ji
你确定总和是100?
MethodMe
MethodMe 博主

引用来自“alexgaoyh”的评论

java 在处理金额的时候,都会有所谓的1分钱的问题,包括财务体系的一些系统,为了解决这个,也会有所谓的平账问题,所以其实会存在一种情况,最后一个人的金额,是总金额减去前面N-1个人的金额算出来的·

嗯嗯,多谢指导
alexgaoyh
alexgaoyh
java 在处理金额的时候,都会有所谓的1分钱的问题,包括财务体系的一些系统,为了解决这个,也会有所谓的平账问题,所以其实会存在一种情况,最后一个人的金额,是总金额减去前面N-1个人的金额算出来的·
月影南溪
月影南溪

引用来自“MethodMe”的评论

我刚才试了试,问题是出现在了这一行,
// 换成分
int total = (int) (money * 100);
这里换的时候,由于精度被舍去的原因 数值已经变了。😄
毕竟浮点型在做运算的时候毕竟不如int好。
MethodMe
MethodMe 博主
我刚才试了试,问题是出现在了这一行,
// 换成分
int total = (int) (money * 100);
这里换的时候,由于精度被舍去的原因 数值已经变了。😄
月影南溪
月影南溪
大概走了一下代码,我觉得在处理的时候,应该把数据转成整型比较好。毕竟 0.1 + 0.2 != 0.3 在有些时候会这样的。大概跑了十次左右,大部分显示99.99999999 或者 100.00000001之类的数据。
Android实现微信自动抢红包

Android实现微信自动抢红包 简介 本文介绍微信自动抢红包的实现方法,主要实现以下几个功能: 自动拆开屏幕上出现的红包 处于桌面或聊天列表时接收到红包信息时自动进入聊天界面并拆红包 日志...

oden
2016/08/27
0
0
ios-微信自动抢红包插件

之前分享过如何搭建theos开发环境, 这次分享下用theos开发一个微信自动抢红包的插件 微信相关类参考来自http://bbs.iosre.com/ ,大家也可以自己结合静态动态分析来找到微信关于红包的几个类...

余成海
2016/03/22
2.2K
0
利用redis + lua解决抢红包高并发的问题

抢红包的需求分析 抢红包的场景有点像秒杀,但是要比秒杀简单点。 因为秒杀通常要和库存相关。而抢红包则可以允许有些红包没有被抢到,因为发红包的人不会有损失,没抢完的钱再退回给发红包的...

涩女郎
2016/09/23
127
0
Android"挂逼"修炼之行---防自动抢红包外挂原理解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangwei0910410003/article/details/54879836 一、前言 春节过年发个红包本来就是为了讨个喜庆,朋友亲戚之间...

尼古拉斯_赵四
2017/03/06
0
0
微信高并发资金交易系统设计方案——百亿红包背后的技术支撑

作者|方乐明 编辑|尾尾每年节假日,微信红包的收发数量都会暴涨,尤以除夕为最。如此大规模、高峰值的业务需要,背后需要怎样的技术支撑?百亿级别的红包规模,如何保证并发性能与资金安全...

umgsai
2017/09/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
今天
5
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
今天
6
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
9
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
5
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部