Java 分数和的计算精度

Java 分数和的计算精度,java,algorithm,math,Java,Algorithm,Math,我有一个数学表达式: ∑(2k+1)/(2k),k=0,∞ , 它是(2k+1)/(2k)形式中所有分数从零到无穷的和 我想创建一个方法,当传递一个整数“n”时,它将输出小数点后有n位的结果。可以在此处查看前100位的表达式: 这是我的代码,我已经尝试过了 package pi.strategy; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import jav

我有一个数学表达式:

∑(2k+1)/(2k),k=0,∞ , 它是(2k+1)/(2k)形式中所有分数从零到无穷的和

我想创建一个方法,当传递一个整数“n”时,它将输出小数点后有n位的结果。可以在此处查看前100位的表达式:

这是我的代码,我已经尝试过了

package pi.strategy;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Tester {

    public static BigInteger factorial(long k) {
        return LongStream.range(2, k + 1).mapToObj(BigInteger::valueOf).reduce(BigInteger.ONE,
                (current, factSoFar) -> factSoFar.multiply(current));
    }

    protected static BigDecimal strategy(int precision) {


        return IntStream.range(0, precision).mapToObj(i -> computeMember(i, precision + 2))
               .reduce(BigDecimal.ZERO, (current, sumSoFar) -> sumSoFar.add(current));
    }


    static BigDecimal computeMember(int n, int scale) {


        final BigDecimal dominator = new BigDecimal((2 * n) + 1);
        final BigDecimal enumenator = new BigDecimal(factorial(2 * n));
        // System.out.println("Temp Result:" + dominator.divide(enumenator, scale,
        // RoundingMode.HALF_UP));
        BigDecimal res = dominator.divide(enumenator, scale, RoundingMode.HALF_UP);

        return res;



    }

    public static void main(String... args) {
        System.out.println(strategy(6));

    }

}
问题是,当我添加分数时,有时它们会溢出,并在末尾创建额外的数字。 对于策略(6),它输出额外的数字2.71828179,而不是2.718281


对于策略(5),它输出错误答案2.7182787,而不是2.71828。你知道问题出在哪里吗?我怎样才能正确地将其限制为精确的输出?

你的代码的问题是,结果在每一步后都被舍入,因此舍入误差被求和

您应该使用一个分数类(比如这里描述的:)并在过程结束时提取十进制表示

编辑

我不是Java开发人员,所以我没有在我的机器上设置合适的开发环境。我已尝试更新您的代码以使用我先前链接的BigFraction类:

package pi.strategy;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Tester {
    public static BigInteger factorial(long k) {
        return LongStream.range(2, k + 1).mapToObj(BigInteger::valueOf).reduce(BigInteger.ONE,
                (current, factSoFar) -> factSoFar.multiply(current));
    }

    protected static BigFraction strategy(int precision) {
        return IntStream.range(0, precision).mapToObj(i -> computeMember(i, precision + 2))
               .reduce(BigFraction.ZERO, (current, sumSoFar) -> sumSoFar.add(current));
    }


    static BigFraction computeMember(int n, int scale) {
        final BigDecimal numerator = new BigDecimal((2 * n) + 1);
        final BigDecimal denominator = new BigDecimal(factorial(2 * n));

        return new BigFraction(numerator, denominator);
    }

    public static void main(String... args) {
        final BigFraction result = strategy(6);
        System.out.println(result);
        System.out.println(result.toBigDecimal());
    }
}

重构此代码可能更有效,这样它就不会使用阶乘函数,或者阶乘被缓存,并且不必从1开始每次重新计算。

这是否回答了您的问题?不,不是真的,我正试图在运行时停止加法。想象一下,如果计算整数需要1小时,而你只需要前5位或前10位。这是我的目标,当我们达到精度时停止计算。如果在运行时停止加法是你的目标,你应该投资数学。要计算给定精度需要多少项,请查看泰勒定理,特别是在。