繁体   English   中英

为什么在尝试使用java.math.BigInteger找出pi的值时,java给出奇怪的结果?

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

我试图通过计算等式中圆周上可能存在的点数来计算pi的值:

如果周长为(c x ,c y ),并且半径为r:
那么,r 2 = c x 2 + c y 2

但是当我使用以下代码在Java中实现它时:

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();

}
}

当我使用代码运行程序时:

new Engine(2).start();

我得到以下输出:

跑:

-100 100 10000 9801 9604 9409 9216 9025 8836 8649 8464 8281 8100 7921 7744 7569 7396 7225 7056 6889 6724 6561 6400 6241 684 6084 5929 5776 5625 5476 5329 5184 5041 4900 4761 4624 4489 4356 4225 4096 3969 3844 3721 3600 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 961900841841784729676 625576576529484441400361361324289289256225196196169144121100 81 64 49 36 25 16 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 8836 9025 9216 9409 9604 9801 10000 100%Pi-> 0.01 BUILD SUCCESSFUL(总时间:0秒)

指出pi的值为0.01。

可能是什么问题以及如何解决?

差不多了 看第二个, for它一定是

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

看线

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

它应该包含compareTo因为您必须将那些位于圆内的对象(不仅限于圆上的对象)进行取舍。 一定是

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

面积必须使用radius.pow(2)计算

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

我调整了您的解决方案。 :)

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();
        }
    }
}

输出:

Area 3141549
PI 3.141549

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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