【问题标题】:Is there an error in this program? Calculating PI simulating the throwing of darts JAVA这个程序有错误吗?计算 PI 模拟投掷飞镖 JAVA
【发布时间】:2015-02-12 10:45:12
【问题描述】:

我应该编写一个程序,通过模拟在正方形的内切圆上投掷飞镖来计算 PI。它将为 x 和 y 值(坐标点)生成随机数,如果 x^2+y^ 小于或等于 1,则飞镖确实击中了圆圈,否则没有(未命中)。 然后它使用以下公式计算 pi:pi = 4 *(命中/总投掷)。 这类似于布冯的针头实验。 正如您在下面看到的,我已经编写了代码,但是当我编译它时,pi 的值甚至没有接近 3.14 :(

 /**
 * This program is intended to calculate the value of pi by simulating throwing darts at a dart                  *board.
 * 
 * @author Nataly Carbonell
 * @version 12/13/2014
 */
import java.util.Scanner;
import java.util.Random;
public class Darts
{
public static double[] calcPi(int d, int t)
{


     int hit = 0;
     int miss = 0;
     double [] posX = new double[d];
     double [] posY = new double[d];
     double[] pi = new double[t];
    for(int i = 0; i < t; i++)
    {
        for(int index = 0; index < d; index++)
        {   
            posX[index] = 2 * Math.random() + - 1;
            posY[index] = 2 * Math.random() + - 1;





            if((Math.pow(posX[index], 2) + Math.pow(posY[index], 2)) <= 1)
            {
                hit++;
            }

            else if ((Math.pow(posX[index], 2) + Math.pow(posY[index], 2))> 1)
            {
                miss++;
            }

    }

    pi[i] = (4 * (hit / d));
    }
   return pi;
}

  public static double calcPiAverage(double[] p, double t)
   {
    double average = 0;
    double sum = 0;
    for(int i = 0; i < t; i++)
    {
      sum += p[i];
    }
    average = sum / t;
    return average;
    }

    public static void printOutput(double [] p, double ave, int t)
    {
    for(int i = 0; i < t; i++)
    {
        System.out.print("Trial [" + i + "]: pi = ");
        System.out.printf("%5.5f%n", p[i]);


    }
    System.out.printf("Estimate of pi = %5.5f", ave);
   }

   public static void main(String[] args)
  {
   Scanner in = new Scanner(System.in);

   System.out.println("How many darts per trial? ");
   int darts = in.nextInt();
   System.out.println("How many trials? ");
   int trials = in.nextInt();

   double [] pi = new double[trials];
   pi = calcPi(darts, trials);

   double piAverage = calcPiAverage(pi, trials);

   printOutput(pi, piAverage, trials);



    }
 }

【问题讨论】:

  • 如果它没有产生预期的结果,那么是的。听起来你有一个错误。也许你应该尝试调试它。
  • 我已经试过很多次了。我只是想让别人检查一下,也许他或她看到了我眼睛没有看到的东西。
  • 你得到的 pi 值到底是多少?
  • 因为它要求用户输入,所以它会有所不同。但通常大于 5.0 的数字,即使值是双精度值,它们的小数点后也不会总是有零。
  • 我会试试这个:posX[index] = 2 * Math.random() - 1posY[index] = 2 * Math.random() - 1+ 应该没有理由在那里。

标签: java random methods static


【解决方案1】:

主要问题可能是您的整数除法:将您的hit 和/或d 转换为double,然后在这里取比率:(4 * (hit / d))。如果我正确理解您的代码,您可能还想在index 循环之外但在i 循环内重置hit

再想一想:这种估计 pi ​​的蒙特卡洛方法收敛极其缓慢,因此您可以采取任何措施来加快速度。由于您可以根据hitd 的值计算miss,因此您不需要else if 子句。而且由于您根本不使用miss,因此您甚至不需要计算它。 (你也可以通过只在正 xy 象限中投掷飞镖来做得更好,但我在下面的代码中没有这样做)。

这是我编辑的代码:

 /**
 * This program is intended to calculate the value of pi by simulating throwing darts at a dart                  *board.
 * 
 * @author Nataly Carbonell
 * @version 12/13/2014
 */
import java.util.Scanner;
import java.util.Random;
public class Darts
{
public static double[] calcPi(int d, int t)
{


     int hit = 0;
     int miss = 0;
     double [] posX = new double[d];
     double [] posY = new double[d];
     double[] pi = new double[t];
    for(int i = 0; i < t; i++)
    {
        hit = 0;
        for(int index = 0; index < d; index++)
        {   
            posX[index] = 2 * Math.random() + - 1;
            posY[index] = 2 * Math.random() + - 1;

            if((Math.pow(posX[index], 2) + Math.pow(posY[index], 2)) <= 1)
            {
                hit++;
            }

    }

    pi[i] = (4 * ((double)hit / d));
    }
   return pi;
}

  public static double calcPiAverage(double[] p, double t)
   {
    double average = 0;
    double sum = 0;
    for(int i = 0; i < t; i++)
    {
      sum += p[i];
    }
    average = sum / t;
    return average;
    }

    public static void printOutput(double [] p, double ave, int t)
    {
    for(int i = 0; i < t; i++)
    {
        System.out.print("Trial [" + i + "]: pi = ");
        System.out.printf("%5.5f%n", p[i]);


    }
    System.out.printf("Estimate of pi = %5.5f", ave);
   }

   public static void main(String[] args)
  {
   Scanner in = new Scanner(System.in);

   System.out.println("How many darts per trial? ");
   int darts = in.nextInt();
   System.out.println("How many trials? ");
   int trials = in.nextInt();

   double [] pi = new double[trials];
   pi = calcPi(darts, trials);

   double piAverage = calcPiAverage(pi, trials);

   printOutput(pi, piAverage, trials);



    }
 }

【讨论】:

  • 好吧,在转换之后,我现在得到小数点后的数字 ^_^ 但值仍然不接近 pi :( 并且在索引之外但在 i 循环内重置命中后,值变得更短(小于 1) 但仍不接近 pi :(
  • 它对我有用(你纠正了hit 计数器的位置吗?)- 尝试 1000000 飞镖和 1 次试验:我得到 3.14321(就像我说的,它不会很快收敛...)
  • 如果我尝试 1000000 并且不止一次试验,我会得到第一次试验 3.14321 但其他试验的数字更大......很奇怪。
  • 哦,看起来改变命中的位置很有效! ^_^ 耶谢谢!
  • 我的意思是每次试用后都必须重置命中 :) 谢谢 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多