平常会偶尔随机或者心血来潮选组幸运数字,支持一下福利和体育事业嘛。某天想想这样无规律的投注是不是有更好更大概率中奖的方式呢,比如双色球2元一注,固定一个蓝球(先只考虑保底蓝球中奖5元),第一次不中,第二次加倍投注,直到中奖为止,看起来是稳赚不赔的,只是这样需要多少成本时间,有多大概率稳赚不赔?
期数 | 本期投注数 | 本期投注 | 累积投注数 | 累积投注 | 中奖 | 累积盈亏 |
1 | 1 | 2 | 1 | 2 | 5 | +3 |
2 | 2 | 4 | 3 | 6 | 10 | +4 |
3 | 4 | 8 | 7 | 14 | 20 | +6 |
4 | 8 | 16 | 15 | 30 | 40 | +10 |
5 | 16 | 32 | 31 | 64 | 90 | +26 |
可以看出,投注数是呈指数级增长的,也确实盈亏是正数,再往后手算已经有点麻烦,于是想通过java代码来模拟下这个过程。
随机选号
先写一个生成中奖号码的方法,主要用到Random随机类,另外就是去重了
/**
* 生成双色球中奖号码
* @param blue
* @return
*/
public static int[] createColorNumbers(Integer blue) {
//定义一个动态初始化数组,存储7个数字
int[] colorNumer = new int[7];
//遍历数组,每一个位置生成中奖号码。
Random r = new Random();
// 遍历前6个位置不重复的红球号码(1-33)
// map存储已经产生的红球
Map<Integer,Integer> redMap =new HashMap<>();
for (int i = 0; i < colorNumer.length - 1; i++) {
while (true) {
int red = r.nextInt(33) + 1;
if (!redMap.containsKey(red)) {
//没有产生过的红球加入中奖号码
colorNumer[i] = red;
redMap.put(red,red);
break;
}
}
}
//蓝球范围1-16,可以指定蓝球号码
if(blue ==null) {
colorNumer[6] = r.nextInt(16) + 1;
}else{
colorNumer[6] = blue;
}
return colorNumer;
}
判断中奖
再写判断中奖方法,循环遍历比较数组,规则参考官网
/**
* 判断中奖情况和金额
* @param luckNumbers
* @param buyNumers
* @return
*/
public static Long hitJudge(int[] luckNumbers, int[] buyNumers) {
//判断是否中奖了
int redHit = 0;
int blueHit = 0;
// 判断红球命中数
for (int i = 0; i < buyNumers.length - 1; i++) {
for (int j = 0; j < luckNumbers.length - 1; j++) {
//每次找到了相等的,意味着当前号码命中了
if (buyNumers[i] == luckNumbers[j]) {
redHit ++;
break;
}
}
}
// 判断蓝球是否命中
blueHit = buyNumers[6] == luckNumbers[6] ? 1 : 0;
//判断中奖情况和金额,官方规则,假设当前最高1000W
Long max = 10000000L;
if (blueHit == 1 && redHit < 3) {
return 5L;
}else if (blueHit == 1 && redHit == 3 || blueHit == 0 && redHit == 4) {
return 10l;
}else if (blueHit == 1 && redHit == 4 || blueHit == 0 && redHit == 5) {
return 200L;
}else if (blueHit == 1 && redHit == 5) {
return 3000L;
}else if (blueHit == 0 && redHit == 6) {
return max*3/10; //二等奖当期高等奖奖金的30%。
}else if (blueHit == 1 && redHit == 6) {
return max;
}else {
return 0L;
}
}
测试一下选号效果
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("----第"+i+"次投注----");
// 模拟购买的号码
int[] buyNumers = createColorNumbers(null);
// 投注号码
System.out.print("投注号码:");
print(buyNumers);
//模拟开奖号码
int[] luckNumbers = createColorNumbers(null);
System.out.print("开奖号码:");
print(luckNumbers);
//判断中奖情况,返回中奖金额
Long j = hitJudge(luckNumbers, buyNumers);
System.out.println("中奖金额:"+j);
}
}
模拟运行
接下来就是验证上面的假设,先固定一个幸运蓝球,我的幸运数字13,未中奖加倍投注,遇到中奖中止进入下一轮。模拟100轮看看盈亏情况。
public static void main(String[] args) {
// 累积赚的金额
double winMoneyAll = 0;
// 累积投入的金额
double buyMoneyAll = 0;
// 累积投注期数
int cishuAll = 0;
int times = 100;
// 固定蓝球
Integer blue =13;
for(int i=0;i<times;i++) {
// 赚的金额
double winMoney = 0;
// 投入的金额
double buyMoney = 0;
// 购买的注数,从1开始
double orders = 1;
// 投注期数
int cishu = 0;
while (true) {
cishu++;
// System.out.println("第"+i+"轮"+cishu+"次投注");
// 模拟购买的号码
int[] buyNumers = createColorNumbers(blue);
// 投注号码
//模拟开奖号码
int[] luckNumbers = createColorNumbers(null);
/*// 投注号码
System.out.print("投注号码:");
print(buyNumers);
// 投注号码
System.out.print("开奖号码:");
print(luckNumbers);*/
//判断中奖情况,返回中奖金额
Integer j = hitJudge(luckNumbers, buyNumers);
orders=orders*2;//投注翻倍
winMoney = winMoney + (j * orders);
buyMoney = buyMoney + (orders * 2);// 2元一注
// 如果中奖了就停止
if (j > 0) {
// System.out.println("中奖了:" + j);
break;
}
}
winMoneyAll += winMoney;
buyMoneyAll += buyMoney;
cishuAll +=cishu;
System.out.println("第"+i+"轮:本轮投注期数" + cishu + ";金额:" + buyMoney + ";中奖金额:" + winMoney + ";盈亏:" + (winMoney - buyMoney));
}
System.out.println("累积模拟" + times + "轮;累积投入金额:" + buyMoneyAll + ";累积中奖金额:" + winMoneyAll + ";累积盈亏:" + (winMoneyAll - buyMoneyAll)+";中奖平均所需期数:"+(cishuAll/times)+",中奖平均所需投注金额"+(buyMoneyAll/times));
}
执行结果发现,虽然盈亏一定是正的,但是运气稍微不好所需的的投注本钱可是天文数字,而且耗费的期数也是相当久的,看来是有保证赚大奖的办法,但是估计没有这样的财富能力和寿命去实现了。
再看看完全随机能不能中大奖。
public static void main(String[] args) {
// 累积投注期数
int cishuAll = 0;
int times = 10;
for(int i=0;i<times;i++) {
// 赚的金额
double winMoney = 0;
// 投入的金额
double buyMoney = 0;
// 投注期数
int cishu = 0;
while (true) {
cishu++;
// 模拟购买的号码
int[] buyNumers = createColorNumbers(null);
//模拟开奖号码
int[] luckNumbers = createColorNumbers(null);
//判断中奖情况,返回中奖金额
Integer j = hitJudge(luckNumbers, buyNumers);
// 如果中大奖了就停止
if (j == 10000000) {
break;
}
}
cishuAll +=cishu;
System.out.println("第"+i+"轮:本轮投注期数" + cishu + "次中大奖");
}
System.out.println("累积模拟" + times + "轮;中大奖平均所需期数:"+(cishuAll/times));
}
这个时间比人类历史还悠久。所以,代码告诉我们,彩票玩玩就好,别抱希望也别投入精力金钱太多