【问题标题】:generating pi to nth digit java生成pi到第n位java
【发布时间】:2011-12-03 19:21:26
【问题描述】:

我想知道如何生成第 n 位的 pi。我有几个基本的想法。

  1. 使用Math.PI 并提高精度(如果可能的话)
  2. 使用欧拉公式生成 pi 但即使在这里,我也需要提高精度(我认为)
  3. 还有 Srinivasa Ramanujan 生成 PI 的公式,该公式以其快速收敛而闻名。这个公式似乎很难实现。我相信,我还必须在这里提高 deicmal 精度。

简而言之,无论哪种方式,我都需要根据第 n 个数字来提高 BigDecimal 的精度。我将如何将BigDecimal 的精度提高到第 n 位?另外,如果有更好更快的方法,请您指出正确的方向。

编辑:我只想生成 PI。我不想用于计算。这是一个关于如何使用 BigDecimal 来实现生成 PI 的想法的问题。

【问题讨论】:

  • 您真的需要生成 Pi 还是需要它来进行计算?
  • 这是关于计算 pi 背后的数学问题,还是关于如何使用 BigDecimal 的问题?
  • 我只是用BigDecimal来实现PI公式,不需要PI来计算,我只想生成它。

标签: java precision bigdecimal pi


【解决方案1】:
  • Math.PI 的类型为 double。这意味着大约 15 个十进制数字的精度,这就是您拥有的所有数据;没有什么能神奇地使额外的 PI 数字出现。
  • BigDecimal 具有任意精度。 setScale() 允许您创建具有任意精度的 BigDecimal 对象,并且大多数算术方法会根据需要自动提高精度,但当然精度越高,所有计算都会越慢。
  • 具有讽刺意味的是,实现 Ramanujan 公式最困难的部分是常数因子中的 sqrt(2),因为 BigDecimal 没有内置 sqrt(),所以你必须自己编写。

【讨论】:

  • 但是对于平方根,即使是百万(或十亿)位的精度,旧的 Heron 方法也能快速收敛。
  • 对于 sqrt(2) 部分,我可以不只使用预定义的值吗? 1.41421356,还是会以某种方式改变计算?
  • @user681159:好吧,只要您希望您的 PI 值比“预定义值”更精确,您就需要更多位数的 sqrt(2)。
  • @user681159:如果你想根据一个特定的常数因子计算一个非常精确的结果,你不能用这个因子的不精确近似来做到这一点,这不是很明显吗?跨度>
  • 对不起,我错过了。放我一马。
【解决方案2】:

你需要使用MathContext来提高BigDecimal的精度

例如

MathContext mc = new MathContext(1000);
BigDecimal TWO = new BigDecimal(2, mc);

重要的是,您在计算中使用的所有BigDecimals 都使用MathContext。 Heron 的方法应该给你 1000 位的精度,只有 10 次迭代和 100 万位的 20 次迭代,所以它肯定足够好。 另外,创建所有常量BigDecimals,例如26390 只在程序开始时出现一次。

【讨论】:

  • Heron的方法是什么意思?
  • @user681159 Heron 的方法与用于平方根的 Newton-Raphson 方法一致,以防您熟悉后者。否则:它通过x_(n+1) = 1/2*(x_n + a/x_n) 找到sqrt(a) 的更好近似值。它收敛于所有a > 0 和任何起始值x_0 > 0。如果您从一个相当好的近似值开始,则在每一步中,正确数字的数量都会增加一倍(大约)。
【解决方案3】:

你可以使用这个代码

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

public final class Pi {

private static final BigDecimal TWO = new BigDecimal("2");
private static final BigDecimal FOUR = new BigDecimal("4");
private static final BigDecimal FIVE = new BigDecimal("5");
private static final BigDecimal TWO_THIRTY_NINE = new BigDecimal("239");

private Pi() {}

public static BigDecimal pi(int numDigits) {

  int calcDigits = numDigits + 10;

  return FOUR.multiply((FOUR.multiply(arccot(FIVE, calcDigits)))
    .subtract(arccot(TWO_THIRTY_NINE, calcDigits)))
    .setScale(numDigits, RoundingMode.DOWN);
}

 private static BigDecimal arccot(BigDecimal x, int numDigits) {

BigDecimal unity = BigDecimal.ONE.setScale(numDigits,
  RoundingMode.DOWN);
BigDecimal sum = unity.divide(x, RoundingMode.DOWN);
BigDecimal xpower = new BigDecimal(sum.toString());
BigDecimal term = null;

boolean add = false;

for (BigDecimal n = new BigDecimal("3"); term == null ||
  term.compareTo(BigDecimal.ZERO) != 0; n = n.add(TWO)) {

  xpower = xpower.divide(x.pow(2), RoundingMode.DOWN);
  term = xpower.divide(n, RoundingMode.DOWN);
  sum = add ? sum.add(term) : sum.subtract(term);
  add = ! add;
}
return sum;
}
}

resource

【讨论】:

  • 这段代码有问题,在某些情况下会导致无限循环;-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 2016-12-19
  • 1970-01-01
相关资源
最近更新 更多