简体   繁体   中英

Why does java gives odd results while trying to find out the value of pi using java.math.BigInteger?

I am trying to compute the value of pi by counting the number of points which may be there in circumference using the equation:

If the point of Circumference is (c x ,c y ), and the radius is r:
then, r 2 = c x 2 +c y 2

But when I implement it in java using the following code:

package ani.pi.gen;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 *
 * @author ani
 */
public class Engine {
private BigInteger x,pimag;
private final BigInteger radius;
public Engine(int digits){
    radius=new java.math.BigInteger("10").pow(digits);
    pimag=new BigInteger("0");
    x=new BigInteger("-"+radius);
    System.out.println(x+" "+radius);
}
public int percent=0;
private int lp=0;
public void start(){
    Thread t=new Thread(() -> {
        for(;x.compareTo(radius)<=0;x=x.add(new BigInteger("1"))){
            System.out.println(x.pow(2));
            for(BigInteger y=new BigInteger(""+radius);y.compareTo(radius)>=0;y=y.subtract(new BigInteger("1"))){
                if(x.pow(2).add(y.pow(2)).equals(radius.pow(2))){
                    pimag=pimag.add(new BigInteger("1"));
                    System.out.println(pimag+" "+x+" "+y);
                }
            }
            percent=(x.add(radius).divide(radius.multiply(new BigInteger("2")))).multiply(new BigInteger("100")).intValueExact();
            if(percent!=lp){
                System.out.println(percent+"%");
                lp=percent;

            }

        }
        System.out.println("Pi -> "+new BigDecimal(pimag.toString()).divide(new BigDecimal(radius+"")));
    });
    t.start();

}
}

When I run the program using the code:

new Engine(2).start();

I get the following output:

run:

-100 100 10000 9801 9604 9409 9216 9025 8836 8649 8464 8281 8100 7921 7744 7569 7396 7225 7056 6889 6724 6561 6400 6241 6084 5929 5776 5625 5476 5329 5184 5041 4900 4761 4624 4489 4356 4225 4096 3969 3844 3721 3600 3481 3364 3249 3136 3025 2916 2809 2704 2601 2500 2401 2304 2209 2116 2025 1936 1849 1764 1681 1600 1521 1444 1369 1296 1225 1156 1089 1024 961 900 841 784 729 676 625 576 529 484 441 400 361 324 289 256 225 196 169 144 121 100 81 64 49 36 25 16 9 4 1 0 1 0 100 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961 1024 1089 1156 1225 1296 1369 1444 1521 1600 1681 1764 1849 1936 2025 2116 2209 2304 2401 2500 2601 2704 2809 2916 3025 3136 3249 3364 3481 3600 3721 3844 3969 4096 4225 4356 4489 4624 4761 4900 5041 5184 5329 5476 5625 5776 5929 6084 6241 6400 6561 6724 6889 7056 7225 7396 7569 7744 7921 8100 8281 8464 8649 8836 9025 9216 9409 9604 9801 10000 100% Pi -> 0.01 BUILD SUCCESSFUL (total time: 0 seconds)

Which states the value of pi is 0.01.

What maybe the problem and how to solve it?

You almost got it. Look at the second for it must be

for (BigInteger y = new BigInteger("" + radius); 
     y.compareTo(new BigInteger("-"+radius)) >= 0; 
     y = y.subtract(new BigInteger("1")))

Look at line

if(x.pow(2).add(y.pow(2)).equals(radius.pow(2))){

it should contain compareTo as you must take those that lie inside the circle, not only on the circle. Must be

if (x.pow(2).add(y.pow(2)).compareTo(radius.pow(2)) <= 0). 

The area must be calculated with radius.pow(2)

System.out.println("Pi -> " + new BigDecimal(
                                 pimag.toString()).divide(
                                 new BigDecimal(radius.pow(2) + "")));

I tweaked your solution. :)

package javaapplication38;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

public class JavaApplication38
{

    public static void main(String[] args)
    {        
        new Engine(BigInteger.TEN.pow(2)).start();
    }

    public static class Engine
    {        
        final BigInteger radius    ;
        final BigInteger negRadius ;
        final BigInteger r2        ; //The force awakens on December 18, 2015.

        public static final BigInteger TWO = new BigInteger("2");    

        public Engine(BigInteger radius)
        {
            this.radius = radius;
            negRadius   = radius.negate();
            r2          = this.radius.pow(2);
        }

        public Engine(int radius)
        {
            this(new BigInteger("" + radius));
        }      

        public void start()
        {
            Runnable r = new Runnable()
            {
                public void run()
                {                    
                    BigInteger area = BigInteger.ZERO; //area of the circle

                    //calculate circle's area
                    //let's walk through all the points (x;y)
                    for (BigInteger x = new BigInteger(negRadius.toString());
                            x.compareTo(radius) <= 0; 
                            x = x.add(BigInteger.ONE))
                    {                        
                        for (BigInteger y = new BigInteger(negRadius.toString());
                                y.compareTo(radius) <= 0;
                                y = y.add(BigInteger.ONE))
                        {
                            //System.out.format("Point %s, %s%n", x.toString(), y.toString());
                            //if square is in the circle add square's area to the area of the circle
                            if (x.pow(2).add(y.pow(2)).compareTo(r2) <= 0)
                            {
                                area = area.add(BigInteger.ONE);
                            }                            
                        }                        
                    }                    
                    System.out.println("Radius " + radius.toString());
                    System.out.println("Area " + area.toString());                    
                    System.out.println("PI   " + new BigDecimal(area).divide(new BigDecimal(r2)));                                                             
                }
            };
            new Thread(r).start();
        }
    }
}

Output:

Area 3141549
PI 3.141549

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM