简体   繁体   English

为什么BigDecimal的除法返回0?

[英]Why is this division with BigDecimal returning 0?

I am using the Chudnovsky algorithm to compute PI: 我正在使用Chudnovsky算法来计算PI:

Here is the code: 这是代码:

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Scanner;

public class main {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int summationUpperLimit;
        int precision;

        System.out.println("Enter the summation upper limit: ");
        summationUpperLimit = reader.nextInt();

        System.out.println("Enter the precision: ");
        precision = reader.nextInt();

        System.out.println(calculatePI(summationUpperLimit, precision));
    }

    private static int calculateFactorial(int n) {
        int factorial = 1;

        for (; n > 1; n--) {
            factorial = factorial * n;
        }

        return factorial;
    }

    private static BigDecimal calculatePI(int summationUpperLimit, int precision) {
        BigDecimal reciprocalOfPI = BigDecimal.ZERO;
        reciprocalOfPI.setScale(precision - 1, BigDecimal.ROUND_HALF_UP);

        for (int k = 0; k <= summationUpperLimit; k++) {
            BigDecimal numerator = BigDecimal.valueOf(12 * Math.pow(-1, k) * calculateFactorial(6 * k) * (13591409 + 545140134 * k));
            numerator.setScale(precision - 1, BigDecimal.ROUND_HALF_UP);
            BigDecimal denominator = BigDecimal.valueOf(calculateFactorial(3 * k) + Math.pow(calculateFactorial(k), 3) * Math.pow(640320, 3 * k + 1.5));
            denominator.setScale(precision - 1, BigDecimal.ROUND_HALF_UP);
            // The issue is the line below:
            reciprocalOfPI = reciprocalOfPI.add(numerator.divide(denominator, BigDecimal.ROUND_HALF_UP));
        }

        return reciprocalOfPI.pow(-1, MathContext.DECIMAL128);
    }
}

I set the following input: 我设置以下输入:

summationUpperLimit = 0
precision = 100

In debugging mode, I checked the output: 在调试模式下,我检查了输出:

numerator = 163096908
denominator = 512384048.99600077
reciprocalOfPI = 0 (this value was taken after the division)

163096908 / 512384048.99600077 doesn't equal 0 so why is the expression reciprocalOfPI = reciprocalOfPI.add(numerator.divide(denominator, BigDecimal.ROUND_HALF_UP)); 163096908 / 512384048.99600077不等于0,为什么表达式reciprocalOfPI = reciprocalOfPI.add(numerator.divide(denominator, BigDecimal.ROUND_HALF_UP)); setting reciprocalOfPI to 0? reciprocalOfPI设置为0?

My justification for setting scale = precision - 1 : 我的理由是设置scale = precision - 1

  1. Precision is the total number of digits. 精度是数字的总数。 Scale is the number of digits after the decimal place. 小数位数是小数点后的位数。

  2. In PI, there is only 1 digit before the decimal. 在PI中,小数点前只有1位数字。

  3. precision = scale + 1 and therefore scale = precision - 1 precision = scale + 1 ,因此scale = precision - 1

It's probably caused by 这可能是由于

reciprocalOfPI.setScale(precision - 1, BigDecimal.ROUND_HALF_UP);

which should be 应该是

reciprocalOfPI = reciprocalOfPI.setScale(precision - 1, BigDecimal.ROUND_HALF_UP);

BigDecimal is immutable. BigDecimal是不可变的。 All its "mutating" methods return a new BigDecimal, leaving the original one unchanged. 它的所有“变异”方法都返回一个新的BigDecimal,而原始的则保持不变。

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

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