买彩票能中大奖?用 Java 盘点常见的概率悖论

2025-12-13 0 698

引言

《双色球头奖概率与被雷劈中的概率哪个高?》
《3 人轮流射击,枪法最差的反而更容易活下来?》
让我们用 Java 来探索 ta 们!

悖论 1:著名的三门问题

规则描述:你正在参加一个游戏节目,你被要求在三扇门中选择一扇:其中一扇后面有一辆车;其余两扇后面则是山羊。你选择了一道门,假设是一号门,然后知道门后面有什么的主持人,开启了另一扇后面有山羊的门,假设是三号门。他然后问你:“你想选择二号门吗?请问若想获得车,参赛者应该换二号门吗?

论证:分析需求,拆解为如下代码

/**
* <p> 三门问题解决方案 </p>
* @author yuanfeng.wang
* @since 2023/8/29
*/
import java.util.Random;

public class ThreeDoorSolution {
  public static void main(String[] args) {
    // 模拟执行1万次,打印获胜的概率
    threeDoor(10000);
  }
  /**
  * 三门问题逻辑拆解
  * @param numSimulations 总共执行多少轮游戏
  */
  private static void threeDoor(int numSimulations) {
    int switchWins = 0;
    int stayWins = 0;

    Random random = new Random();
    for (int i = 0; i < numSimulations; i++) {
      // 随机确定车所在的门
      int carDoor = random.nextInt(3);

      // 玩家随机选择一扇门
      int playerChoice = random.nextInt(3);

      // 主持人随机打开一扇门:要求该门不是玩家选择的,且必须是羊
      int openedDoor;
      do {
        openedDoor = random.nextInt(3);
      } while (openedDoor == carDoor || openedDoor == playerChoice);

      // 换门后的选择:不能是打开的门,不能是玩家选择的门,则是交换之后的门
      int finalChoice;
      do {
        finalChoice = random.nextInt(3);
      } while (finalChoice == playerChoice || finalChoice == openedDoor);

      // 计算是否换门获胜
      if (finalChoice == carDoor) {
        switchWins++;
      }
      // 计算不换门获胜
      if (playerChoice == carDoor) {
        stayWins++;
      }
    }
    // 输出结果
    System.out.println(\"在 \" + numSimulations + \" 次模拟中:\");
    System.out.println(\"换门获胜的概率:\" + (double) switchWins / numSimulations);
    System.out.println(\"不换门获胜的概率:\" + (double) stayWins / numSimulations);
  }
}
// 模拟运行,打印结果如下
// 在 10000 次模拟中:
// 换门获胜的概率:0.6679
// 不换门获胜的概率:0.3321

结论:三门问题看似一道简单的概率题,几十年来却一直引发巨大争议,持两种不同观点的人基本是五五开;事实上始终选择换门的玩家,获胜的概率 2/3,而保持原方案的胜率只有 1/3

悖论 2:双色球我能中大奖

规则描述:从 1-33 个红色球中随机选出 6 个,再从 1-16 个蓝色球中随机选择 1 个,最终开奖出一注 6+1 组合球,无顺序要求;

  • 一等奖:中 6 红 + 1 蓝
  • 二等奖:中 6 红
  • 三等奖:中 5 红 + 1 蓝
  • 四等奖:中 4 红 + 1 蓝,或只中 5 个红
  • 五等奖:中 3 红 + 1 蓝,或只中 4 个红
  • 六等奖:中 1 蓝

论证:分析玩法,计算一等奖中奖率,从 33 个红球样本中选择 6 个,计算总共的组合数,即数学公式 C (n, m) = n!/((n-m)! * m!),代入计算 C (33, 6) = 33!/((33-6)! * 6!) = 1107568,再乘以 16,最终得出一等奖获奖概率 1/17721088。

分析规则,以下代码展示了开奖一次,购买 N 注时,打印中奖信息的程序,当代入 N=500 万时,多次执行,可以很轻松打印出一等奖

import java.util.*;
/**
* <p>双色球随机模拟</p>
* @author yuanfeng.wang
* @since 2023/8/29
*/
public class SsqSolution {
  private static Random random = new Random();
  /**
  * 开奖的红球
  */
  private static Set<Integer> winningRedBalls;
  /**
  * 开奖的蓝球
  */
  private static int winningBlueBall;
  // 静态块初始化一组开奖号码
  static {
    // 篮球 01-16
    winningBlueBall = random.nextInt(16) + 1;

    // 红球 01-33生成6个
    winningRedBalls = new HashSet<>();
    while (winningRedBalls.size() < 6) {
      int num = random.nextInt(33) + 1;
      winningRedBalls.add(num);
    }
  }
  public static void main(String[] args) {
    play(500_0000);
  }
  /**
  *
  * @param num 运行一次程序只开一次奖,此参数表示总共购买多少注
  */
  public static void play(int num) {
    System.out.println(\"\\n本期开奖号码:\");
    System.out.println(\"红球:\" + winningRedBalls + \" 篮球:\" + winningBlueBall);
    for (int i = 0; i < num; i++) {
      playOnce();
    }
  }
  private static void playOnce() {
    Set<Integer> userRedBalls = getUserSelectedRedBalls();
    int userBlueBall = getUserSelectedBlueBall();

    int redBallMatch = countMatchingBalls(userRedBalls, winningRedBalls);
    boolean blueBallMatch = (userBlueBall == winningBlueBall);

    if (redBallMatch == 6 && blueBallMatch) {
      System.out.println(\"\\n恭喜你中了一等奖!\");
      System.out.println(\"玩家购买的号码:\");
      System.out.println(\"红球:\" + userRedBalls + \" 蓝球:\" + userBlueBall);
    } else if (redBallMatch == 6) {
      System.out.println(\"\\n恭喜你中了二等奖!\");
    } else if (redBallMatch == 5 && blueBallMatch) {
//      System.out.println(\"\\n恭喜你中了三等奖!\");
    } else if (redBallMatch == 5 || (redBallMatch == 4 && blueBallMatch)) {
//      System.out.println(\"\\n恭喜你中了四等奖!\");
    } else if (redBallMatch == 4 || (redBallMatch == 3 && blueBallMatch)) {
//      System.out.println(\"\\n恭喜你中了五等奖!\");
    } else if (blueBallMatch) {
//      System.out.println(\"\\n恭喜你中了最小奖!\");
    } else {
      //没中奖,不打印记录
    }
  }
  /**
  * 返回玩家选择的6个红球,范围1-33,不重复
  */
  private static Set<Integer> getUserSelectedRedBalls() {
    Set<Integer> userRedBalls = new HashSet<>();
    while (userRedBalls.size() < 6) {
      int num = random.nextInt(33) + 1;
      userRedBalls.add(num);
    }
    return userRedBalls;
  }
  /**
  * 玩家选择的1个蓝球,范围1-16
  */
  private static int getUserSelectedBlueBall() {
    return random.nextInt(16) + 1;
  }
  /**
  * 匹配中了几个红球
  * @return 中红球个数
  */
  private static int countMatchingBalls(Set<Integer> userBalls, Set<Integer> winningBalls) {
    int count = 0;
    for (int ball : userBalls) {
      if (winningBalls.contains(ball)) {
        count++;
      }
    }
    return count;
  }
}

结论:排除其它因素,头奖概率约 1700 万分之 1,这个结论并不直观,例举如下几个进行对比

1. 一家祖孙三代人的生日都在同一天的概率约为 27 万分之一

2. 小行星撞击地球的概率保守推测是 200 万分之一

3. 生出全男或全女四胞胎的概率约为 352 万分之一

悖论 3:三个枪手

描述:三个小伙子同时爱上了一个姑娘,为了决定他们谁能娶这个姑娘,他们决定用枪进行一次决斗。A 的命中率是 30%,B 比他好些,命中率是 50%,最出色的枪手是 C,他从不失误,命中率是 100%。由于这个显而易见的事实,为公平起见,他们决定按这样的顺序:A 先开枪,B 第二,C 最后。然后这样循环,直到他们只剩下一个人。那么 A 第一枪应该怎么打?谁活下来的概率最大?

论证:每个人的目标都是活下来,为了目标寻找最好的策略。以下开始分人讨论

A:

  • 若 A 开枪射杀了 B,则下个开枪是 C,C 会 100% 射杀 A,这不是一个好策略
  • 若 A 开枪射杀了 C,则下一轮 B 会有 50% 的几率杀掉自己
  • 若 A 开枪未打中,则下一轮可以坐山观虎斗,所以 A 最好的策略看似是故意打空枪更好一些

B:

  • 若 A 已经将 C 射杀,此时 B 与 A 互相射击,B 的生存率高于 A
  • B 只能选择射杀 C,因为只要 C 活着,都会优先射杀 B

C:

  • 先消除威胁大的 B,然后再杀掉 A,只要自己有开 2 枪的机会,直接获胜

结论:需求太复杂,暂未实现生存概率计算??,欢迎补充悖论 3 的代码论证过程

作者:京东保险王苑沣

来源:京东云开发者社区 转载请注明来源

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 买彩票能中大奖?用 Java 盘点常见的概率悖论 https://www.zuozi.net/36420.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务