** 首先我想说,这个问题是“受家庭作业启发的”:它是统计力学中的作业,不涉及编程,所以我把作业标记放在了外面。**
我试图在 java 中实现 Buffon 的针法来估计 pi,但我的结果太偏了,不是很多 - 但是有一个著名的结果使用针/空间比为 5/6,它应该比我提供更好的估计米得到。我希望您能帮助我理解为什么我的结果不准确。
(对于该方法,维基百科中有一个很好的解释,带有动画)
我的想法是这样的:
如果针中心的垂直位置+垂直投影(半长*sin(角度))大于一条线的位置并且减去垂直投影的位置小于一条线的位置:那么这意味着针的一端在线的上方,另一端在线的下方,这意味着有交叉点。
(这几乎是中间值定理)
我尝试过的事情:
- 对于大于 0.99 的任何随机数,将随机数更改为 1 并没有什么不同。
- 检查位置/(线之间的距离)和 sin(角度)值是否有效,在 [0,1) 范围内并且分布大致均匀;例如:在 149100 次迭代中,75000~ 两个数字都大于 0.5。
- 以数学方式(中间值定理)检查(并证明)迭代仅在引脚与线相交时计算在内。
这是实现(我是编程新手,所以我很乐意收到有关代码本身的评论):
import java.util.Scanner;
import java.lang.Math;
public class BuffonNeedle {
public static Scanner scan = new Scanner(System.in);
public static double checkNumber(double min) {
String input = scan.next();
if (input.equalsIgnoreCase("END")) {
System.exit(0);
}
try {
double Num = Double.parseDouble(input);
if(Num<=min ) {
System.out.println("Try again: input must be a number greater than "+min);
return checkNumber(min);
}
return Num;
} catch (Exception e) {
System.out.println("Try again: input must be a number greater than "+min);
return checkNumber(min);
} // end try-catch
}// end checkNumber method
public static void main(String[] args) {
double d = 0; // distance between two lines
double l = 0; // size of needle
double angle = 0;
double position = 0; // the position of the center of the pin (in the range of 0 to the distance between two lines)
double estimateOfPi =0; // the result we will finally give (should be Pi)
double iterations = 0;
double intersections = 0; // number of times needle intersected with line, the number is a double due to calculation later
int count = 0;
System.out.println();
System.out.println("Typing END at any stage will cause the program to terminate, otherwise it will run a 100 times.");
System.out.println("if you would like to cheat try- needle: 5 , space: 6 , iterations: a multiply of 213 (like 149100) ");
// cheating is actually for any multiply of (d*355/(2*l)), provided the expression is an integer
System.out.println();
while (count<100) {
if (count >=1) System.out.println("Lets try again.");
System.out.println("Please insert the size of the needle:");
l = checkNumber(0);
System.out.println("Please insert the size between two lines:");
d = checkNumber(l);
System.out.println("How many iterations would you like? (the more iterations - the better chance for close estimate)");
iterations = checkNumber(0);
for(int i=0;i<iterations;i++) {
angle = Math.random()*Math.PI;
position = d * Math.random();
// checking to see if there is indeed an intersection - using the intermediate value theorem.
if( ( ( position + l*Math.sin(angle)/2 >= d ) && ( position - l*Math.sin(angle)/2 <= d ) ) ||
( ( position + l*Math.sin(angle)/2 >= 0 ) && ( position - l*Math.sin(angle)/2 <= 0 ) ) ) {
intersections++;
} // end if
} // end for
estimateOfPi = (2*l*iterations) / (d*intersections);
intersections=0;
System.out.println("π = "+estimateOfPi);
count++;
} // end while
} // end main
} // end class