公司有个红包分发业务模块,需要红包随机生成金额,克提供参数为:
1、红包金额(最小精确到厘:0.001,数据库是用int表示,1元也就是1000厘)
2、红包发放数量
3、红包金额上限
4、红包金额下限
5、金额精度(精度可以理解为随机数能精确到小数哪一位,如范围为:0.01~0.5,如果精确到分的随机数为0.34 or 0.340,如果精确到厘:0.345)
1,2,3,4,5都可以由用户输入或选择,程序可进行判断是否参数不符计算,意思就是:
如果金额为10元,数量为10个,上限就不能大于10-0.001*9=9.991之类的
而且,金额是随用户输入,没有限制10的倍数或者100的倍数,可能会是2546
数量也是由用户输入,也可能为3254等不规则数字
需要程序使用用户金额生成在上限下限范围内随机缺固定的数量的红包个数,我想了好久了
由于数学比较差,而且红包金额可以根据精度调控后面小数位数
我写了一个,但是感觉没那么满意
public class Red {
private int remain;//金额,单位厘
private int count;//个数
private Precision precision;//精度
private int max;//上限,单位厘
private int min;//下限,单位厘
private int[] redPool;
private int index;
public static void main(String[] args) {
int count = 100;
Red red = Red.newInstance(10 * 1000, count, Precision.FEN, 1 * 1000, 5 * Precision.FEN.getPre());
int sum = 0;
for (int i = 0; i < count; i++) {
int money = red.getRed();
sum += money;
System.out.println(money);
}
System.out.println("---------------" + sum);
}
public int getRed() {
return index < count ? redPool[index++] : 0;
}
public static Red newInstance(int money, int count, Precision precision, int max, int min) {
Red red = new Red(money, count, precision, max, min);
String msg;
if ("".equals(msg = red.validate())) return red;
else throw new RuntimeException(msg);
}
private Red(int money, int count, Precision precision, int max, int min) {
this.remain = money;
this.count = count;
this.precision = precision;
this.max = max;
this.min = min;
init();
}
private void init() {
redPool = new int[count];
int remain_ = remain;
for (int i = 0; i < count - 1; i++) {
int max = getRealMax(remain_, count - i);
int min = getRealMin(remain_, count - i);
int money = ((int)(Math.random() * (max - min + precision.getPre())) + min)
/ precision.getPre() * precision.getPre();//[min, realMax]
remain_ -= money;
redPool[i] = money;
}
redPool[count - 1] = remain_;
randomPool();
}
private void randomPool() {
for (int i = 0; i < count; i++) {
int index = (int) (Math.random() * count);
int temp = redPool[i];
redPool[i] = redPool[index];
redPool[index] = temp;
}
}
private int getRealMax(int remain, int count) {
int calMax = remain - ((count - 1) * min);
return Math.min(calMax, max);
}
private int getRealMin(int remain, int count) {
int calMin = remain - ((count - 1) * max);
return Math.max(calMin, min);
}
public int getRemain() {
return remain;
}
public void setRemain(int remain) {
this.remain = remain;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getMax() {
return max;
}
public void setMax(int max) {
this.max = max;
}
public int getMin() {
return min;
}
public void setMin(int min) {
this.min = min;
}
public Precision getPrecision() {
return precision;
}
public void setPrecision(Precision precision) {
this.precision = precision;
}
private String validate() {
String msg = "";
if (remain <= 0) {
msg = "余额不能为0";
} else if (remain % precision.getPre() != 0) {
msg = "余额的精度不对";
} else if (count <= 0) {
msg = "红包个数必须为正数";
} else if (max % precision.getPre() != 0) {
msg = "上限的精度不对";
} else if (max <= min) {
msg = "上限必须大于下限";
} else if (min % precision.getPre() != 0) {
msg = "下限的精度不对";
} else if (min <= 0) {
msg = "下限必须大于0";
} else if (getRealMax(remain, count) < getRealMin(remain, count)) {
msg = "上下限设置错误";
}
return msg;
}
}
enum Precision {
LI(1),
FEN(10),
JIAO(100),
YUAN(1000);
private int pre;
private Precision(int pre) {
this.pre = pre;
}
public int getPre() {
return pre;
}
}
https://blog.csdn.net/huluwaaaa/article/details/63682748
简单的实现就是逻辑采用随机数的方式
比如 10元发10个数量,按照你说的10*1000 = 10000厘
1.生成个9999以内的随机数 比如说生成5300 计数1
2.10000-5300 = 4700 再次生成一个4700内的随机数 计数+1
3.依次类推 最后到9次的时候 使用10000-生成所有随机数之和这样就生成最后一个金额