程序中经常遇到随机送红包之类的情景,这个随机还得指定概率,比如10%的机率可以得到红包。那么java怎么实现一个简单的概率计算了,见如下例子:

int randomInt =  RandomUtils.nextInt(1,101);
if(randomInt <= 10){ //100里面1个数,小于等于10的概率就是10%
//do something
}

RandomUtils工具类是commons-lang3包里面的

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>

如果要在某个数字区间产生一个随机数,区间内部在不同的片段几率不同如何实现呢?经常有这样的场景,比如,随机赠送红包,范围0.1元-100元,0.1-1元的概率是90%,1元-10元的概率是9%,10元-100元的概率是1%,也就是说数额越大得到的几率越小!实现的原理如下图:

原理就是,将范围分割成一个个子范围(片段),具体采用哪个范围,再用机率判断。片段机率可以依次排好序,映射成[1,100]之间的数字。然后随机一个[1,100]之间的数,该数落在哪个区间,就采用哪个片段产生随机数。具体源代码如下:

package com.hdwang;

import org.apache.commons.lang3.RandomUtils;

import java.util.ArrayList;
import java.util.List; /**
* 按几率产生随机数
* 例如,产生0.1-100的随机数,0.1-1的几率是90%,1-10的几率是9%,10-100的几率是1%
*/
public class RateRandomNumber { /**
* 产生随机数
* @param min 最小值
* @param max 最大值
* @return 随机结果
*/
public static double produceRandomNumber(double min,double max){
return RandomUtils.nextDouble(min,max); //[min,max]
} /**
* 按比率产生随机数
* @param min 最小值
* @param max 最大值
* @param separates 分割值(中间插入数)
* @param percents 每段数值的占比(几率)
* @return 按比率随机结果
*/
public static double produceRateRandomNumber(double min,double max,List<Double> separates,List<Integer> percents){
if(min > max){
throw new IllegalArgumentException("min值必须小于max值");
}
if(separates == null || percents==null || separates.size()==0){
return produceRandomNumber(min,max);
}
if(separates.size() +1 != percents.size()){
throw new IllegalArgumentException("分割数字的个数加1必须等于百分比个数");
}
int totalPercent = 0;
for(Integer p:percents){
if(p<0 || p>100){
throw new IllegalArgumentException("百分比必须在[0,100]之间");
}
totalPercent += p;
}
if(totalPercent != 100){
throw new IllegalArgumentException("百分比之和必须为100");
}
for(double s:separates){
if(s <= min || s >= max){
throw new IllegalArgumentException("分割数值必须在(min,max)之间");
}
}
int rangeCount = separates.size()+1; //例如:3个插值,可以将一个数值范围分割成4段
//构造分割的n段范围
List<Range> ranges = new ArrayList<Range>();
int scopeMax = 0;
for(int i=0;i<rangeCount;i++){
Range range = new Range();
range.min = (i==0 ? min:separates.get(i-1));
range.max = (i== rangeCount-1 ?max:separates.get(i));
range.percent = percents.get(i); //片段占比,转换为[1,100]区间的数字
range.percentScopeMin = scopeMax +1;
range.percentScopeMax = range.percentScopeMin + (range.percent-1);
scopeMax = range.percentScopeMax; ranges.add(range);
}
//结果赋初值
double r = min;
int randomInt = RandomUtils.nextInt(1,101); //[1,100]
for(int i=0;i<ranges.size();i++){
Range range = ranges.get(i);
//判断使用哪个range产生最终的随机数
if(range.percentScopeMin <= randomInt && randomInt <= range.percentScopeMax){
r = produceRandomNumber(range.min,range.max);
break;
}
}
return r;
} public static class Range{
public double min;
public double max;
public int percent; //百分比 public int percentScopeMin; //百分比转换为[1,100]的数字的最小值
public int percentScopeMax; //百分比转换为[1,100]的数字的最大值
} public static void main(String[] args) {
List<Double> separates = new ArrayList<Double>();
separates.add(1.0);
separates.add(10.0);
List<Integer> percents = new ArrayList<Integer>();
percents.add(90);
percents.add(9);
percents.add(1);
for(int i=0;i<100;i++) {
double number = produceRateRandomNumber(0.1, 100, separates, percents);
System.out.println(String.format("%.2f",number));
}
}
}

JAVA实现概率计算(数字不同范围按照不同几率产生随机数)的更多相关文章

  1. java根据概率生成数字

    /** * JAVA 返回随机数,并根据概率.比率 * @author zhanglei * */ public class MathRandom { /** * 0出现的概率为%50 */ publ ...

  2. Java中精确的数字计算类BigDecimal

    在日常开放当中需要我们计算数字,利率.通常Java的做法是使用Math相关的API.但是,这样做是不够精确的,由于float和double不能进行计算,如果强行进行计算会使得计算不准确.造成难以挽回的 ...

  3. HMM的概率计算问题和预测问题的java实现

    HMM(hidden markov model)可以用于模式识别,李开复老师就是采用了HMM完成了语音识别. 一下的例子来自于<统计学习方法> 一个HMM由初始概率分布,状态转移概率分布, ...

  4. 算法笔记_155:算法提高 概率计算(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 生成n个∈[a,b]的随机整数,输出它们的和为x的概率. 输入格式 一行输入四个整数依次为n,a,b,x,用空格分隔. 输出格式 输出一行 ...

  5. Java实现 蓝桥杯 算法提高 概率计算

    算法提高 概率计算 时间限制:1.0s 内存限制:256.0MB 问题描述 生成n个∈[a,b]的随机整数,输出它们的和为x的概率. 输入格式 一行输入四个整数依次为n,a,b,x,用空格分隔. 输出 ...

  6. Java完成简单猜数字游戏v2.0

    猜数字游戏v2.0 优化了获取随机数.输入数据超出边界值的代码,并增加了异常处理,能够在玩家输入错误数据错误时给出可靠指引,希望对和我一样的新人有帮助, 最后希望有大神愿意帮我解决代码优化的问题,谢谢 ...

  7. MT2018笔试题之计算数字位数

    一.计算数字位数 1.题目 给定一个数字T,计算从1到T的所有正整数的位数和.比如T=13,则12345678910111213有17位数字. 输入描述 3 13 4 5 输出 17 4 5 2.思路 ...

  8. 计算数字出现的次数 Exercise07_03

    import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:计算数字出现的次数 * */ public class Exercise0 ...

  9. Java 高精度浮点数计算工具

    说起编程中的高精度数值,我第一反应就是double类型了.的确,double阶码11位,尾数52位,几乎能应对任何苛刻的要求......然而,当我天真地尝试用double来算泰勒展开式的函数值,离散代 ...

随机推荐

  1. golang channel 源码剖析

    channel 在 golang 中是一个非常重要的特性,它为我们提供了一个并发模型.对比锁,通过 chan 在多个 goroutine 之间完成数据交互,可以让代码更简洁.更容易实现.更不容易出错. ...

  2. mfc Unicode转 ASNI ,WCHAR 转 CHAR

    知识点: 宽字符转多字节字符 多字节字符转宽字符 什么是ANSI,什么又是UNICODE呢?其实这是两种不同的编码方式标准,ANSI中的字符采用8bit,而UNICODE中的字符采用16bit 在VC ...

  3. 11.8 开课二个月零四天 (Jquery)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 编译安装php时遇到virtual memory exhausted: Cannot allocate memory

    有时候用vps建站时需要通过编译的方式来安装主机控制面板.对于大内存的VPS来说一般问题不大,但是对于小内存,比如512MB内存的godaddy VPS来说,很有可能会出现问题,因为编译过程是一个内存 ...

  5. zabbix问题之snmp监控端口流量断图

    zabbix之snmp监控端口断图问题 在使用zabbix的snmp方式的监控端口流量时,某一个图总是断断续续的(被监控设备有较大的端口流量),经常会出现几分钟内没有图像的问题. 端口流量断图原因: ...

  6. Activity猫的一生-故事解说Activity生命周期

    大家好,关于Android中Activity的生命周期,网上大多数文章基本都是直接贴图.翻译API,比较笼统含糊不清. 我就用故事来说一说: 有个人叫User,TA养了几只猫,有只猫叫Activity ...

  7. svn commit时报错 File already exists

    第一步: 删除当前文件所在文件夹,提交commit 第二步: 新建刚才删除的文件夹,并将先前需要commit的文件放到此文件夹下,再次commit 提交

  8. LintCode——数字统计

    数字统计:计算数字k在0到n中的出现的次数,k可能是0~9的一个值 样例:例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现1出现 ...

  9. 吴恩达《AI For Everyone》_练习英语翻译_待更新

    AI For Everyone https://www.coursera.org/learn/ai-for-everyone 讲师: Andrew Ng (吴恩达) CEO/Founder Landi ...

  10. 科普贴 | 数字钱包MetaMask安装使用详解,活用MetaMask轻松驾驭以太坊

    MetaMask 是一款浏览器插件钱包,不需下载安装客户端,只需添加至浏览器扩展程序即可使用,非常方便.它是很多支持 ETH 参投的 ICO 项目推荐使用的钱包之一. 2018年初最火的一个币,应该就 ...