使用循环通过级数扩展估计 PI
Estimate PI with series expansion using loops
我需要通过执行以下系列来估算 PI:
m(i) = 4( 1- 1/3 + 1/5 - 1/7 + 1/9 - 1/11 ...)
这就是我到目前为止所做的:
float mOfI = 1;
System.out.println("i \t \t \t \t m(i)" );
for (int i = 1; i < n; i++) {
float sum = i + 2;
mOfI += 4 * (1 - (1 / sum));
mOfI -= 4 * (1 - (1 / sum));
System.out.println(i + "\t \t \t \t" +mOfI);
}
我知道我在这里遗漏了很多规则,但我怎样才能让它正常工作?我的意思是数学逻辑。我怎样才能正确解决?
请注意系列中的 -+
,所有数字都是奇数,所以我不能使用 i%2
。
估计的 PI 会像 4.0000 , 3.1515, 3.1466 .....
等等。
另外这个question没有得到很好的回答(没有估计真实的PI值)
让它变得简单,找到简单的模式。这里有一个提示
- 先忽略与4的乘法(也可以考虑
每学期)
- 考虑初始denom = 1,所以term = 1/denom = 1
- 寻找规律。请注意,在每一步 newTerm =
(-1)*(1/(denom+2))
。所以在每次迭代中,更新 sum 和 denom
因此。
- n次迭代后,将sum乘以4
float m = 4;
for (int i = 1; i < n; i++) {
if(i%2==0){
m +=4/(2*i+1);
} else {
m -=4/(2*i+1);
}
System.out.println(i + "\t \t \t \t" +m);
}
注意:我使用的是移动应用程序,可能存在语法错误,但您应该明白了。
mOfI
永远不会改变,因为这两条线相互抵消
mOfI += 4 * (1 - (1 / sum));
mOfI -= 4 * (1 - (1 / sum));
试试这个。
double mOfI = 4.0;
System.out.println("i \t \t \t \t m(i)" );
for (int i = 1, d = 3, s = -1;
i < n;
i++, d += 2, s = -s) {
mOfI += 4.0 / (s * d);
System.out.println(i + "\t \t \t \t" +mOfI);
}
您的代码中存在多个问题。
- 首先你应该只将一个加数除以
i
,另一个除以i + 2
,而不是同时除以i + 2
。
- 你在每个被加数上加上
1
,这是错误的,它应该像1 / sum
而不是1 - (1 / sum)
- 下一步
i
需要在每个步骤中推进更多,i+2
甚至 i+4
如果您决定在一个迭代步骤中创建两个被加数
- 如果
n
变大,您很快就会达到 int
和 double
精度的极限,您可能需要 BigInteger
和 BigDecimal
来提供 无限精度 space.
您目前正在制作的系列看起来像:
4 * ((1 - 1 / 1) - (1 - 1 / 1) + (1 - 1 / 2) - (1 - 1 / 2) +- ...)
应该是0
,因为每个部分都相互抵消。
正确的版本应该是这样的:
double result = 0;
// Whether we add or subtract the summand
boolean doAdd = true;
// Start at i = 0 to produce 1 as first denominator,
// else use - instead of + in the code
for (int i = 0; i < n; i++) {
// Advance in steps of 2 and use odd values
// Denominator will be 1, 3, 5, 7, ... for i = 0, 1, 2, 3, ...
double summand = 1 / (2 * i + 1);
if (doAdd) {
// Add it
result += summand;
} else {
// Subtract it
result -= summand;
}
// Toggle the flag
doAdd = !doAdd;
}
// Multiply by 4
result *= 4;
当然,如前所述,您可能需要替换为BigDecimal
。
如果您不想使用额外的标志,也可以使用 if (i % 2 == 0)
而不是 if (doAdd)
。但是这样可能更容易理解。
感谢大家抽出宝贵时间,但我找到了正确的解决方案:
double start = 1; // Start series
double end = 901; // End series
System.out.println("\ni m(i) ");
System.out.println("---------------------");
for (double i = start; i <= end; i += 100) {
System.out.printf("%-12.0f", i);
System.out.printf("%-6.4f\n", estimatePI(i));
}
}
/** Method estimatePI */
public static double estimatePI(double n) {
double pi = 0; // Set pi to 0
for (double i = 1; i <= n; i ++) {
pi += Math.pow(-1, i +1) / (2 * i - 1);
}
pi *= 4;
return pi;
}
这只是一个 Java9 函数式编程练习;你可以用这条线计算圆周率:
double pi = 4 * Stream.iterate(1.0, i -> i < 10000000, i -> i + 2)
.reduce(0.0, (a, d) -> ((d - 1) / 2) % 2 == 0 ? (a + 1 / d) : (a - 1 / d));
Java 8 和 Java 9 示例:
// Java 9
double pi = 4 * Stream.iterate(1.0, i -> i < 10000000, i -> i + 2)
.reduce(0.0, (a, d) -> ((d - 1) / 2) % 2 == 0 ? (a + 1 / d) : (a - 1 / d));
System.out.println(pi);
// Java 8
pi = 4 * Stream.iterate(1.0, i -> i + 2).limit(10000000)
.reduce(0.0, (a, d) -> ((d - 1) / 2) % 2 == 0 ? (a + 1 / d) : (a - 1 / d));
System.out.println(pi);
我需要通过执行以下系列来估算 PI:
m(i) = 4( 1- 1/3 + 1/5 - 1/7 + 1/9 - 1/11 ...)
这就是我到目前为止所做的:
float mOfI = 1;
System.out.println("i \t \t \t \t m(i)" );
for (int i = 1; i < n; i++) {
float sum = i + 2;
mOfI += 4 * (1 - (1 / sum));
mOfI -= 4 * (1 - (1 / sum));
System.out.println(i + "\t \t \t \t" +mOfI);
}
我知道我在这里遗漏了很多规则,但我怎样才能让它正常工作?我的意思是数学逻辑。我怎样才能正确解决?
请注意系列中的 -+
,所有数字都是奇数,所以我不能使用 i%2
。
估计的 PI 会像 4.0000 , 3.1515, 3.1466 .....
等等。
另外这个question没有得到很好的回答(没有估计真实的PI值)
让它变得简单,找到简单的模式。这里有一个提示
- 先忽略与4的乘法(也可以考虑 每学期)
- 考虑初始denom = 1,所以term = 1/denom = 1
- 寻找规律。请注意,在每一步 newTerm =
(-1)*(1/(denom+2))
。所以在每次迭代中,更新 sum 和 denom 因此。 - n次迭代后,将sum乘以4
float m = 4;
for (int i = 1; i < n; i++) {
if(i%2==0){
m +=4/(2*i+1);
} else {
m -=4/(2*i+1);
}
System.out.println(i + "\t \t \t \t" +m);
}
注意:我使用的是移动应用程序,可能存在语法错误,但您应该明白了。
mOfI
永远不会改变,因为这两条线相互抵消
mOfI += 4 * (1 - (1 / sum));
mOfI -= 4 * (1 - (1 / sum));
试试这个。
double mOfI = 4.0;
System.out.println("i \t \t \t \t m(i)" );
for (int i = 1, d = 3, s = -1;
i < n;
i++, d += 2, s = -s) {
mOfI += 4.0 / (s * d);
System.out.println(i + "\t \t \t \t" +mOfI);
}
您的代码中存在多个问题。
- 首先你应该只将一个加数除以
i
,另一个除以i + 2
,而不是同时除以i + 2
。 - 你在每个被加数上加上
1
,这是错误的,它应该像1 / sum
而不是1 - (1 / sum)
- 下一步
i
需要在每个步骤中推进更多,i+2
甚至i+4
如果您决定在一个迭代步骤中创建两个被加数 - 如果
n
变大,您很快就会达到int
和double
精度的极限,您可能需要BigInteger
和BigDecimal
来提供 无限精度 space.
您目前正在制作的系列看起来像:
4 * ((1 - 1 / 1) - (1 - 1 / 1) + (1 - 1 / 2) - (1 - 1 / 2) +- ...)
应该是0
,因为每个部分都相互抵消。
正确的版本应该是这样的:
double result = 0;
// Whether we add or subtract the summand
boolean doAdd = true;
// Start at i = 0 to produce 1 as first denominator,
// else use - instead of + in the code
for (int i = 0; i < n; i++) {
// Advance in steps of 2 and use odd values
// Denominator will be 1, 3, 5, 7, ... for i = 0, 1, 2, 3, ...
double summand = 1 / (2 * i + 1);
if (doAdd) {
// Add it
result += summand;
} else {
// Subtract it
result -= summand;
}
// Toggle the flag
doAdd = !doAdd;
}
// Multiply by 4
result *= 4;
当然,如前所述,您可能需要替换为BigDecimal
。
如果您不想使用额外的标志,也可以使用 if (i % 2 == 0)
而不是 if (doAdd)
。但是这样可能更容易理解。
感谢大家抽出宝贵时间,但我找到了正确的解决方案:
double start = 1; // Start series
double end = 901; // End series
System.out.println("\ni m(i) ");
System.out.println("---------------------");
for (double i = start; i <= end; i += 100) {
System.out.printf("%-12.0f", i);
System.out.printf("%-6.4f\n", estimatePI(i));
}
}
/** Method estimatePI */
public static double estimatePI(double n) {
double pi = 0; // Set pi to 0
for (double i = 1; i <= n; i ++) {
pi += Math.pow(-1, i +1) / (2 * i - 1);
}
pi *= 4;
return pi;
}
这只是一个 Java9 函数式编程练习;你可以用这条线计算圆周率:
double pi = 4 * Stream.iterate(1.0, i -> i < 10000000, i -> i + 2)
.reduce(0.0, (a, d) -> ((d - 1) / 2) % 2 == 0 ? (a + 1 / d) : (a - 1 / d));
Java 8 和 Java 9 示例:
// Java 9
double pi = 4 * Stream.iterate(1.0, i -> i < 10000000, i -> i + 2)
.reduce(0.0, (a, d) -> ((d - 1) / 2) % 2 == 0 ? (a + 1 / d) : (a - 1 / d));
System.out.println(pi);
// Java 8
pi = 4 * Stream.iterate(1.0, i -> i + 2).limit(10000000)
.reduce(0.0, (a, d) -> ((d - 1) / 2) % 2 == 0 ? (a + 1 / d) : (a - 1 / d));
System.out.println(pi);