Java分数相加精度,计算分数和的精度

I have this mathematical expression :

∑(2k+1)/(2k)! , k =0,... ,∞ , it is sum from zero to infinity of all fractions in the form (2k+1)/(2k)!

I want to create a method which when passed an integer "n", it will output me the result with n digits after the decimal point.This expression first 100 digits can be viewed here : https://miniwebtool.com/first-n-digits-of-e/?number=100

Here is my code, what I have attempted

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

}

}

The problem is that when I add fractions, sometimes they will overflow and create extra digits at the end.

In case of strategy(6) , it outputs extra digits 2.71828179 instead of 2.718281

In the case of strategy(5) it outputs wrong answer 2.7182787 instead of 2.71828. Any ideas where is he problem and how can I limit it correctly to output with precision?

解决方案

The problem with your code is that the result is being rounded after each step, and so rounding errors are being summed.

You should use a Fraction class (such as the one described here: https://stackoverflow.com/a/474612) and extract the decimal representation at the end of the process.

EDIT

I'm not a Java developer, so I don't have a proper dev environment set up on my machine. I've tried to update your code to use the BigFraction class I linked earlier:

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

}

}

It may be more efficient to refactor this code so that it doesn't use the factorial function or factorials are cached and don't have to be recomputed each time from 1.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值