在第5次迭代后,因子循环结果不正确
我目前正在进行预微积分,并认为我会制作一个快速程序,它会给我阶乘10的结果。在测试它时,我注意到我在第5次迭代后得到的结果不正确。 但是,前4次迭代是正确的。
public class Factorial { public static void main(String[] args) { int x = 1; int factorial; for(int n = 10; n!=1; n--) { factorial = n*(n-1); x = x * factorial; System.out.printf("%d ", x); } }//end of class main }//end of class factorial
你超过了int
类型(2,147,483,647)的容量,所以你的结果会回绕到最小的int
值。 尝试使用long
来代替。
说到这一点,你目前使用的方法不会得到正确的答案: 实际上 ,你目前正在计算10! ^ 2
10! ^ 2
。
为什么复杂的事情? 您可以轻松地执行以下操作:
long x = 1L; for(int n = 1; n < 10; n++) { x *= n; System.out.println(x); }
1 2 6 24 120 720 5040 40320 362880
显示连续因子直到10!
到达了。
另外,正如其他人所提到的,如果你需要的值大于long
可以支持的值,你应该使用BigInteger
,它支持任意精度。
这是一个整数溢出问题。 使用long
或unsigned long
而不是int
。 (正如@Dunes建议的那样,在使用非常大的数字时,最好的选择是BigInteger
,因为理论上它永远不会溢出)
基本思想是signed int存储-2,147,483,648 to 2,147,483,647
之间的数字,它们存储为二进制位(计算机中的所有信息都存储为1
和0
)
正数在最高有效位中存储为0
,负数在最高有效位中存储为1
。 如果正数在二进制表示中变得太大,则数字将转移到有符号位并将正数转换为负数的二进制表示。
然后,当factorial变得比unsigned int
可以存储的更大时,它将“环绕”并从最重要的(有符号)位丢失结转 – 这就是为什么你看到有时交替正值和负值的模式的原因在你的输出中。
您的阶乘公式不正确。 你将拥有的是:
- 步骤1:n *(n-1)= 10 * 9 = 90 => x = 1 * 90 = 90
- 步骤2:n *(n-1)= 9 * 8 = 72 => x = 90 * 72 = 6480或者,它应该是:10 * 9 * 8 => 720
但是错误的结果来自于你达到其他人指出的int类型的最大值这一事实
你的代码应该是
public class Factorial { public static void main(String[] args) { double factorial = 1; for(int n = factorial; n>=1; n--) { factorial = factorial * n; System.out.printf("%d ", factorial ); } } }
除了其他答案提到的溢出之外,您的因子算法也是不正确的。 10! 应该计算10*9*8*7*6*5*4*3*2*1
,你正在做(10*9)*(9*8)*(8*7)*(7*6)*...
尝试将循环更改为以下内容:
int x = 1; for(int n = 10; n > 1 ; n--) { x = x * n; System.out.printf("%d ", x); }
如果你试图计算更高数字的阶乘,你最终会溢出,但是int
足够大,可以计算10的阶乘。