-2

In a program, I need to display the approximate PI value, which is close to 3.141592653. The program is from The Art and Science of Java Chapter 6 Exercise 3.

Let me outline the exercise. Imagine there is a circle with radius r inscribed inside a square with length of 2r. If a dart is threw in a random fashion, the probability that the dart will fall in the circle is the ratio between the area of the circle and the square, which is PI*r^2/4*r^2, which is the same as PI/4. As a result, the more experiments, the more precise the the value of PI is. Now imagine we are doing it in a coordinates. Randomly choose 2 number, x and y each between -1 and 1. If x^2 + y^2 < 1, the coordinate point will fall into the circle with 1 radius centered in the middle of the coordinates.

Here is the program:

import acm.program.*;

import acm.util.*;

public class ApproxPIValue extends ConsoleProgram{

public void run() {
    int total = 0; //calculating the time the dart falls into the circle.
    for (int a = 0; a < 10000; a++) {
        double x = rgen.nextDouble(-1.0, 1.0);
        double y = rgen.nextDouble(-1.0, 1.0);
        if ((Math.pow(x, 2) + Math.pow(y, 2)) < 1) {
            total++;
        }
    }
    println((double) (total / 10000)*4); // as I mentioned above, the result would be the approximate value of PI/4. By multiplying the result with 4, get the approximate PI value.//
}


/* set RandomGenerator as an instance variable. */
private RandomGenerator rgen = new RandomGenerator();
}

Another question is, is there anyway to print a String without extending any class. As you may notice in the code, I extends ConsoleProgram, which contains the println method. I know there is another method called System.out.print, but when I use it, it doesn't work, even Eclipse doesn't give any warning.

JackDee
  • 1
  • 1
  • 4
  • 2
    I'm confused. You say "Another question is...", but you haven't asked your first question yet. Unless you are referring to the title? Which is confusing itself, because I'm not aware of a primitive type that restricts you to just one digit after the decimal point. – Duncan Jones Jan 22 '14 at 08:48
  • *Is there any primitive type that can contain more than one digit after decimal point?* - Yes, and that's `double`. – Rahul Jan 22 '14 at 08:49
  • You should use `x * x + y * y`: will never be slower than using `Math.pow` – Bathsheba Jan 22 '14 at 08:49
  • I forgot to mention that, of course, the result would be of double data type, which only contain 1 digit after decimal point. But that's because **total** is of **int** data type, if I don't convert the result to **double**, the result would just be **3**. – JackDee Jan 22 '14 at 08:49
  • [This should be a good read](http://stackoverflow.com/q/3144610/2024761). – Rahul Jan 22 '14 at 08:52
  • @R.J, that confused me as well, I converted **total/10000** to double already, but the program gave me **3.0** – JackDee Jan 22 '14 at 08:52
  • @JackDee - That's the problem with Integer Division(the answers below talk about it) which yielded the answer 3 and that when casted to `double` gave *3.0* since it doesn't make sense to simply have a lot of zeros after the decimal point just because it can have that much precision. I hope I'm clear. – Rahul Jan 22 '14 at 08:55
  • @R.J Now it gives me 3 digits after the decimal point, how can I get more? – JackDee Jan 22 '14 at 08:57
  • 1
    That's on the result of the division right? If there isn't a 4th digit, then you won't get it in the output either. Try a divisor and dividend which would yield atleast 5-6 digits. I'm sure you'll be able to see all of those in the output. – Rahul Jan 22 '14 at 09:03

3 Answers3

2
  1. To the question in the title: a double has precision to 15 significant digits, irrespective of where the decimal point is.
  2. In this code

    (double) (total / 10000)*4)
    

    you cast the resut of integer operations to a double. The result has 15 significant digits, but the number it represents is an integer. One way to correct is

    (total / 10_000.0) * 4
    

    (no need to convert to double explicitly).

  3. Use System.out.println() to immediately see the result on-screen. The PrintStream referred to by System.out is a buffered stream which means it doesn't propagate each character to the screen as it is written. It will flush either when the buffer is full or at the sight of a newline character. This is why System.out.print() does not auto-flush.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
0

Since total is an int, total/10000 uses integer division, i.e. it rounds to zero. You seem to try to use floating point division by casting to double, but the actual division happens before the cast is done. Change that line to

println(((double) total / 10000) *4); 

to fix this.

BTW: Java's double has about 16 significant digits.

Njol
  • 3,271
  • 17
  • 32
  • Thanks, I wish to get 16 digits, but I can't even after changing the code. – JackDee Jan 22 '14 at 09:05
  • @JackDee You won't get 16 digits with your code because you divide by `10000`, i.e. you'll get a maximum of 4 digits. To get the full 16 significant digits (i.e. 15 digits after the period because the first '3' of '3.141...' counts as well) you would have to loop 10000000000000000 times which your computer likely can't handle in an acceptable time ;) – Njol Jan 22 '14 at 09:09
  • Thanks for explaining, that's very clear to me. I wish I can vote you up. – JackDee Jan 22 '14 at 09:13
0

Re-reading your question, I suspect the problem is this line:

println((double) (total / 10000)*4);

You are dividing one integer with another, which will result in an integer. You then cast that to a double, but by then the damage is done.

To solve this, force the compiler to treat the 10000 value as a double. This will ensure the result is a double.

println((total / 10000d)*4);
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • Thanks. But I only get 3, sometimes 4, digits. How can I get more? Thanks in advance. – JackDee Jan 22 '14 at 09:04
  • @JackDee I suspect you'd need to improve your algorithm for that. If you are only seeing 3 or 4 digits, then that's all there are to display! I'm not familiar with your algorithm, but perhaps there's a way to up the iterations or do something that improves the accuracy. – Duncan Jones Jan 22 '14 at 09:05