此问题与此帖有关:https://stackoverflow.com/a/35810542/5888956
基本上,我必须编写一个从键盘读取整数的程序,它必须能够显示50!仅使用数组。 (不能使用Biginteger或任何东西) 到目前为止,我得到了这个,感谢前一篇文章的帮助。
import java.util.Scanner;
class Factorial
{
public static void main(String[] args)
{
int n;
Scanner kb = new Scanner(System.in);
System.out.println("Enter n");
n = kb.nextInt();
int [] result = fact(n);
int i = result.length-1;
while (i > 0 && result[i] == 0)
{
i--;
}
System.out.print(n + "! = ");
while (i >= 0)
{
System.out.print(result[i--]);
}
System.out.println();
}
public static int[] fact(int n)
{
int[] a = new int[100];
a[0] = 1;
for (int i = 1; i <= n; i++)
{
int carry = 0;
for(int j = 0; j < a.length; j++)
{
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
return a;
}
}
但我仍然无法理解这里背后的逻辑。 特别是这部分,
for (int i = 1; i <= n; i++)
{
int carry = 0;
for(int j = 0; j < a.length; j++)
{
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
我试图用笔和纸来解决这个问题,这样我才能完全理解它。 (当然还有像4这样的小号!)
所以如果我输入4代表n,4!是24(4 * 3 * 2 * 1)。
在我的逻辑中,当i
1
a[0]
为1
因为我在上面初始化时,但在for循环结束一次后,它是否变为0
?
i = 1, j = 0
x = a[0] * 1 + 0 = 1
a[0] = 0
carry = 1
// ------repeat the loop
i = 2, j = 0
x = a[0] * 1 + 1 = 1
a[0] = 0
carry = 1
因此,我认为这显然不是正确的逻辑。 请有人请帮我理解这个吗?
答案 0 :(得分:1)
阶乘操作只是意味着将一大堆数字相乘,所以从概念上讲,实现起来并不困难。它在代码中实现时很快成为问题的原因是它产生了大量数字,实际上太大而无法保存在一个int
(4个字节)或甚至long
(8个字节)中变量(12!
是您在int
中可以容纳的最大值。否则,我们会做类似的事情:
int fact = 1;
for(int i = 2 ; i <= n ; i++) {
fact *= i;
}
因此,处理此问题的一种方法是将数字视为&#34;数字&#34;,在基数10中。例如,数字2016
可以被视为此数组:{ {1}},这只是说int[] digits = {2, 0, 1, 6}
的另一种方式。
现在让我们假设我们有8位计算机,而且我们无法表示大于2016 = 2*1000 + 0*100 + 1*10 + 6*1
(或255
)的数字。我们不能直接做pow(2,8)-1
,但是,因为乘法是分配的2016*2
,我们可以分解&#34;大&#34;的乘法。将a(b+c) = ab+ac
编号为较小的乘法,如下所示:
2016
2016 → {2, 0, 1, 6} → 2*1000 + 0*100 + 1*10 + 6
现在我们可以像手工一样进行这些小的乘法:
2016 * 2 = (2*1000 + 0 + 1*10 + 6) * 2 = (2*2)*1000 + (2*0) + (2*1)*10 + (2*6)
我们得到2016 * 2 → {2, 0, 1, 6} * 2 → {2*2, 0*2, 1*2, 6*2} → {4, 0, 2, 12}
的第一个数字,所以我们需要结转12
:
1
这正是您的代码所做的:
{4, 0, 2, 12} → {4, 0, 2+1, 2} → {4, 0, 3, 2} = 4032
它需要您的号码或&#34;数字数组&#34; a[0] = 1;
for (int i = 1; i <= n; i++) {
int carry = 0;
for(int j = 0; j < a.length; j++) {
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
,并将数字a
分别乘以a[j]
→i
。如果它大于9,请将额外费用带到下一个数字→x = a[j] * i
,然后将剩余的数字作为数字→carry = x / 10
的值。