看了隔壁的访问量和点赞量酸了。我也水个博客,估计也没人看。
问题分析
1、如何保证金额的随机。
2、保留两位小数后会导致分发的金额与总金额不匹配的问题。
解决方案
1、我们用一个数组来存红包个数个的随机数(ran数组),并且用个变量(sum)累加每个随机数,这样第i个人抢到的红包金额即为 ans[i] = ran[i]*money/sum;
2、我们除的时候会有好多位小数,而我们一般抢红包只有2位小数,所以我们应该只保留两位小数,但是假设有1万个0.001这样的红包每个人抢到的都是0.001,我们只保留两位即我们抢到的金额为0。腾讯含泪血赚10元。(好像也没赚多少。。。),所以我们应该采用如下方案。
double[] ans = new double[num]; //用来存取每个人分到的金额。
double sum2= 0; //用来存取每个分到的金额的和
for(int i=0;i<num;i++)
{
ans[i] = (int)(ran[i]*money/sum * 100); //ran[i]*money/sum 即这个人应该分到的金额,注意ran[i]/sum 因为sum和ran[i]都是随机数所以可以随机分发红包。
sum2 += ans[i]; //(ran[i]*money/sum * 100); 乘100即将小数点后两位变成了整数,然后转换为int即保留了两位小数。
ans[i]/=100;
}
sum2/=100; //将sum2处于一百,即生成小数点后两位
double temp = money - sum2; //temp = money - sum2 temp 即因为每份红包只保留2位小数导致与红包总金额的差值
ans[r.nextInt(num)] += temp; //将这个差值随机加入一个红包内
然后就可以愉快的敲代码了。
主函数代码:
package ex1;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double money;
int num;
Scanner cin = new Scanner(System.in);
do{
System.out.print("请输入红包总金额:");
money = cin.nextDouble();
if(money<0.01) System.out.println("红包总金额不合法,请重新输入。");
}while(money <0.01);
do{
System.out.print("请输入红包个数:");
num = cin.nextInt();
if(num<=0 || num>=10005) System.out.println("红包个数不合法,请重新输入。");
if(money/num < 0.01) System.out.println("每个人分到的钱连0.01都不到,请重新输入份数");
}while(num<=0 ||(money/num < 0.01));
RedPacket rp0 = new RedPacket(money,num);
int[] ran = new int[num]; //用来存取随机数
Random r = new Random();
int sum = 0,x; //sum用来记录所有随机数的和,x用来存取随机数。
for(int i = 0;i<num;i++)
{
x = r.nextInt(100);
sum += x;
ran[i] =x;
}
double[] ans = new double[num]; //用来存取每个人分到的金额。
double sum2= 0; //用来存取每个分到的金额的和
for(int i=0;i<num;i++)
{
ans[i] = (int)(ran[i]*money/sum * 100); //ran[i]*money/sum 即这个人应该分到的金额,注意ran[i]/sum 因为sum和ran[i]都是随机数所以可以随机分发红包。
sum2 += ans[i]; //(ran[i]*money/sum * 100); 乘100即将小数点后两位变成了整数,然后转换为int即保留了两位小数。
ans[i]/=100;
}
sum2/=100; //将sum2处于一百,即生成小数点后两位
double temp = money - sum2; //temp = money - sum2 temp 即因为每份红包只保留2位小数导致与红包总金额的差值
ans[r.nextInt(num)] += temp; //将这个差值随机加入一个红包内
double flag = 0; //检测各个红包金额的和是否可以等于总金额
for(int i = 0;i<num;i++)
{
flag += ans[i];
System.out.printf("%.2f\n",ans[i]);
}
if(Math.abs(flag-money) < 1e-8){
System.out.println("相等");
}else System.out.println("不相等");
}
}
红包类代码:
package ex1;
public class RedPacket {
private double money; ///红包金额
private int num; //红包个数
public RedPacket(double money, int num) {
this.money = money;
this.num = num;
}
public RedPacket(){
}
public double getMoney() {
return money;
}
public int getNum() {
return num;
}
public void setMoney(double money) {
this.money = money;
}
public void setNum(int num) {
this.num = num;
}
}
隔壁链接
可能还有细节没有完善,欢迎各位大佬多多指正。