java - 布冯针(Java实现)

标签 java algorithm pi

** 首先我想说,这道题是“homework-inspired”:是Statistical Mechanics的homework,没有涉及编程,所以我把homework tag去掉了。 **

我已经尝试在 Java 中实现 Buffon 的 needle 方法来估计 pi, 但我的结果太离谱了,相差不大——但有一个著名的结果,使用针/空间比为 5/6,这应该比我得到的估计更好。 我希望您能帮助我理解为什么我的结果不准确。

(对于方法,在wikipedia中有很好的解释,有动画)

我的想法是这样的:

如果针中心的垂直位置+垂直投影(半长*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

最佳答案

I'm a newbie to programming, so I would gladly receive comments about the code itself

这里是:

  1. 不要捕获异常。捕获您预期的一个或多个特定异常,然后让其余异常传播。

  2. 如果您确实捕获了Exception,请确保您处理了所有 可能性。您当前的实现假设问题是无效数字。可能是其他事情;例如标准输入位于 EOF 位置,某些(假设的)错误导致 NPE 等。

  3. 局部变量应该总是以小写字母开头; Num -> num.

  4. 您的checkNumber 处理错误(通过递归)的方式有问题。如果根本原因不是不正确的用户输入,而是重试无法解决的问题,您将以无限递归告终!在 Java 中,这将导致 StackOverflowError ... 和大量堆栈跟踪(如果已打印)。

关于java - 布冯针(Java实现),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19601518/

相关文章:

java - Java thread.stop() 是如何工作的?

java - 我在sql中有数字类型pojo类中对应的映射数据类型是什么

java - 使用 Apache poi 时,ooxml-schemas-1.4.jar 和 poishadow-all.jar 中出现重复错误

java - 在文件中存储对象/充满对象的 map 的最简单方法是什么?

java - 如何使用 Java 泛型来强制执行类型限制

将 8 位转换为等效的缩放 12 位

algorithm - 对包含 7 个整数的数组进行排序的最快方法是什么?

Python 不会打印超过 12 位有效数字。如何更轻松地打印?

perl - 将 Perl 中的 Pi 舍入到小数点后第 100 位?

c++ - 宏 C/C++ 的奇怪行为