起因是看到了里神乐的微博(微博),一下激起了我的兴趣,但是作为一个已经大学毕业一年多的打工人,数学知识早还给老师了,于是就想用程序模拟点的情况,通过统计频率,来逼近概率。
代码放在这
import java.util.ArrayList;
public class test {
public static void main(String[] args){
ArrayList<Double[]> pointValid = new ArrayList<>();
//点在同一侧的次数
double oneSide = 0;
//随机次数
double count = 100000;
//生成点的个数
int validPointNum = 10000;
//几点共半圆
int pointNum = 4;
likou util = new likou(pointNum);
//生成点的队列
for (int i = 0; i < validPointNum; i++) {
pointValid.add(util.getAValidPoint());
}
//统计点在同一侧的次数
for (int i = 0;i < count; i++) {
ArrayList<Double[]> fourPoint = util.getFourPoint(pointValid);
if(util.isOneSide(fourPoint)){
oneSide++;
}
}
//计算频率展示
System.out.println(oneSide/count);
}
}
import java.util.ArrayList;
import java.util.Random;
public class likou {
Random random = new Random();
//几点共半圆
int pointNum = 4;
public likou(int pointNum){
this.pointNum = pointNum;
}
//生成一个点
private Double[] generatePoint(){
Double[] point = {Math.random()*2-1,Math.random()*2-1};
return point;
}
//点是否在原点为(0,0)半径为1的圆内部
private Boolean isValid(Double[] point){
if(point[0]*point[0]+point[1]*point[1] <1){
return true;
}
return false;
}
//其他pointNum-1个点在一个点与原点组成的直线一侧
private Boolean isOneSide(Double[] pointInSide , ArrayList<Double[]> points){
Double k = pointInSide[1]/pointInSide[0];
int upper = 0;
int Below = 0;
for (int i = 0; i < pointNum-1; i++) {
if(points.get(i)[0]*k < points.get(i)[1]){
upper++;
}else if(points.get(i)[0]*k > points.get(i)[1]){
Below++;
}
}
if(upper*Below == 0){
return true;
}
return false;
}
//获取一个圆内的点
public Double[] getAValidPoint(){
Double[] ValidPoint;
do {
ValidPoint = generatePoint();
}while(!isValid(ValidPoint));
return ValidPoint;
}
//在点组成列表中随机取pointNum个
public ArrayList<Double[]> getFourPoint(ArrayList<Double[]> points){
ArrayList<Double[]> FourPoint = new ArrayList<Double[]>();
for (int i = 0; i < pointNum; i++) {
FourPoint.add(points.get(random.nextInt(points.size()-1)));
}
return FourPoint;
}
//pointNum个点在同一个半圆内
public Boolean isOneSide(ArrayList<Double[]> points){
for (int i = 0; i < pointNum; i++) {
ArrayList<Double[]> temp = (ArrayList<Double[]>) points.clone();
temp.remove(i);
if(isOneSide(points.get(i),temp)){
return true;
}
}
return false;
}
}
大概的思路就是在原点为(0,0)半径为1的圆内随机生成一万个点,随机取四个点,随机十万次,统计下四点共半圆的次数除以十万。得出频率
还好我还及得圆和直线的方程,判断四点共半圆,只要存在其他点都在任意一个点与圆心确定的直线一侧就可以了。
执行得出的结论居然是二分之一。
数学解法,可以参考下将点转化为半径来处理的这种思路,四个点可以确认四条直径,一个点可能在直径上的两个半径上,而四条半径相邻时,点在同一个半圆内,那根据古典概率用指定的情况数量除以可能出现的情况数就可以了。用2n除以2的n次方。