一道数学题引发的惨案!4只小鸭子在一个圆形的大水池中,分别随机的出现圆圈中任意一点。4只鸭子在同一半圆内的概率是多少?

答案在文章结尾,不感兴趣的可以直接看答案
也就是昨天在渣男开车群中惊现一张照片。4只鸭子!
在这里插入图片描述
然后一群渣男开始了激烈的讨论,有说1/8的 有说3/4的 有说1/3的…反正说什么的都有
唉你说都是男的好好滴妹子不聊,怎么讨论起来数学题了?好好的厨子不切菜,反倒玩起了乐器?我非常不屑于他们的行径,并积极的参与到了讨论之中。

我向着Java高声呐喊到
来吧!赐予我让他们闭嘴的力量吧!

一上来就暴力求解:思路是
只要存在两点的连线将圆分为大小两半,使其余两点在较小半侧,那么就判定为真,否则为假。写了半天感觉算下来的有点奇怪这里就不多说了。
在这里插入图片描述
换了一个思路,每一只鸭子都能与圆心用来唯一的确定一条直线,只要剩下三只在这条直线的同一侧就算在一半内。

上来我就定义了一个Point类,可以随机生成点出现在以原点为圆心,1为半径的圆内的点

class Point {
    private double x;
    private double y;
    //假设圆半径为1,圆心为原点
    public Point() {
        double a  = 0;double b  = 0;
        do{
            x = Math.random()*2-1;
            y = Math.random()*2-1;
        }while (outOfCircle(x,y));
    }
    @Override
    public String toString() {
        return "["+x+","+y+"]";
    }
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    private boolean outOfCircle(double a, double b){ return a*a+b*b>1; }
    public double getX() {
        return x;
    }
    public double getY() {
        return y;
    }
}

直线的类我一开始想的比较复杂包含了截距b (其实不怎么需要)其类为Line

class Line {
    private double k;
    private double b;
    public Line(double k, double b) {
        this.k = k;
        this.b = b;
    }
    public double getK() {
        return k;
    }
    public double getB() {
        return b;
    }
    public double getXWhenY0() {
        return -b / k;
    }
    public double getYWhenX0() {
        return b;
    }
}

以下是函数的实现部分

public class Main {
    public static void main(String[] args) {
        int in = 0;
        int count =10000000;
        for (int i = 0; i < count; i++) {
            Point[] ps =  build4Duck();
            if (isOrNotInHalf(ps)) {
                in += 1;
            }
        }
        System.out.println("经过"+count+"实验,其中4只鸭子都在一侧的情况为"+in+"次");
        System.out.println("概率为:"+(double)in/count);
    }
 
    private static Point[] build4Duck(){
        Point[] ps = new Point[4];
        for(int i=0;i<ps.length;i++)
            ps[i] = new Point();
        return ps;
    }
 
    private static boolean isOrNotInHalf(Point[] ps) {
        for(int i = 0;i<ps.length;i++){//跟距一个点坐标和圆心将圆分成两半
            Line line = getLine(new Point(0,0),ps[i]);
            if(line==null)return false;
            boolean isInHalf = true;
            //找到其余的第一个点是在直线上方还是下方
            int ano = (i==0)?1:0;
            boolean onOrDown = ps[ano].getY()-line.getK()*ps[ano].getX()>0;//斜率b是否大于0
            for(int j  = ano+1;j<ps.length;j++){
                if(i==j)continue;
               isInHalf = isInHalf
                       &&(onOrDown==(ps[j].getY()-line.getK()*ps[j].getX()>0));//其余各点是否ano位置相同
            }
            if(isInHalf)return true;
        }
        return false;
    }

    private static Line getLine(Point one, Point ano) {
        double x1 = one.getX();
        double y1 = one.getY();
        double x2 = ano.getX();
        double y2 = ano.getY();
        //斜率y = kx + b
        double k = ((double) (y2 - y1)) / (x2 - x1);
        if (k == 0) return null;
        double b = y1 - k * x1;
        return new Line(k, b);
    }
}

运行结果是
在这里插入图片描述当当当当~完美解决!
四只鸭子在同侧的概率为

1/2

没想到吧居然有一半的几率4只鸭子在同一侧。

然后呢。某群友在谷歌搜索Duck Pond Probability得到了外国友人的解答思路
在这里插入图片描述翻译一下,设第“1”只鸭子恰好在0°的位置。剩下的每只鸭子都可能与这只鸭子在同侧的概率都是1/2,然而每只鸭子都可能当这个鸭王。所以结果为4*(1/21/21/2)

百度怎么都搜不到的题谷歌居然一下就解决了。这对我打击有点大…以后一定要好好用谷歌搜索。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页