我写了一个用Leibniz公式计算PI数的程序:
[
我写了一个for循环,初始化类型为"int",循环工作正常,但是当我将初始化类型更改为"long"时,结果会发生变化.这仅在循环时间超过十亿时才会发生.这使得"int-loop"计算PI比"长循环"更准确.我不知道为什么会这样.请帮我理解这个问题.谢谢!这是我的代码.
public static void main(String[] args) { double result1 = 0; double result2 = 0; double sign = 1; for (int i = 0; i <= 1607702095; i++) { result1 += sign/(2 * i + 1); sign *= -1; } sign = 1; for (long j = 0; j <= 1607702095; j++) { result2 += sign/(2 * j + 1); sign *= -1; } System.out.println("result1 " + result1 * 4); System.out.println("result2 " + result2 * 4); System.out.println("pi " + Math.PI); }
结果是:
result1 3.141592653576877 result2 3.1415926529660116 pi 3.141592653589793
Eran.. 34
实际上,你的第一个循环int
在计算(2 * i + 1)
何时i
足够大时会溢出,所以我不会依赖它的输出.
另一方面,第二个循环产生更正确的输出,因为(2 * j + 1)
它不会溢出,因为它执行long
乘法.
这使得"int-loop"计算PI比"长循环"更准确
这可能只是一个巧合,因为int
循环中的计算溢出.
实际上,你的第一个循环int
在计算(2 * i + 1)
何时i
足够大时会溢出,所以我不会依赖它的输出.
另一方面,第二个循环产生更正确的输出,因为(2 * j + 1)
它不会溢出,因为它执行long
乘法.
这使得"int-loop"计算PI比"长循环"更准确
这可能只是一个巧合,因为int
循环中的计算溢出.
因为你的线路正在溢出
result1 += sign/(2 * i + 1);
其中值2*i
越过最大整数值
int range是 -2,147,483,648 to 2,147,483,647
但当你2*i
为更大的值做的时候它超过了这个范围.
最好坚持下去,long
这样可以提供正确的输出.
2 * i
当我靠近你的循环结束溢出最大int值是2147483647
使用long操作不会溢出.
正确的程序使用long类型.可能因为某些奇怪的行为会在正确的PI周围添加和删除值,溢出会瞬间计算到更接近正确PI的值.
我认为更改少量值的for循环的限制会将最终结果更改为距离正确的PI更远的值.
你有整数溢出.
signed int的最大容量是(2 ^ 31)-1,或2,147,483,647.
(1,607,702,095*2)是3215404190,大于2,147,483,647.
当你将i改为long时,你将i的容量增加到(2 ^ 63)-1.
注意到每个人都指向整数溢出,但您可能需要一个解决方案.(如果您已经有一个,请忽略以下:))
在(2 * i + 1)
代码的一部分中有溢出,你应该i
在for循环中最大化(Integer.MAX_VALUE / 2 - 1)
,这导致:
for (int i = 0; i <= (Integer.MAX_VALUE / 2 - 1); i++) { result1 += sign/(2 * i + 1); sign *= -1; }
你也可以做(Long.MAX_VALUE / 2 - 1)
很长一段时间,但它会运行很长时间.