使用for循环计算阶乘

15

目前我有这段代码,它的作用是计算阶乘。

int numberInt = int.Parse(factorialNumberTextBox.Text);

for (int i = 1; i < numberInt; i++)
{
  numberInt = numberInt * i;
}

factorialAnswerTextBox.Text = numberInt.ToString();

出于某种原因它不能工作,我不知道为什么。例如,我将输入3并得到答案-458131456,这似乎非常奇怪。

感谢任何帮助。


8
在循环中请使用另一个变量来替代 numberInt 的循环条件。请注意不要在循环内部改变 numberInt 变量的值。 - I4V
你正在 for 循环中更改变量 numberInt 的值,而相同的变量用于比较。 - Amar
1
此外,请注意,如果使用32位的int,您只能计算到12的阶乘。也许考虑改用64位的long。编辑:好吧,long最多只能计算到20的阶乘。:) 编辑:来试试BigInteger - Chris Sinclair
16个回答

37
int numberInt = int.Parse(factorialNumberTextBox.Text);
int result = numberInt;

for (int i = 1; i < numberInt; i++)
{
    result = result * i;
}

factorialAnswerTextBox.Text = result.ToString();

顺便说一下:这通常不是计算阶乘的正确方法。在开始计算之前,您需要对输入进行检查,以防起始值为1或更低,这种情况下您需要手动返回1。

另外一点:这也是递归方法可用的完美示例。

int Factorial(int i)
{
    if (i <= 1)
        return 1;
    return i * Factorial(i - 1);
}

1
请注意,这段代码没有处理0!的情况,其结果应为1。 - Matthew Watson
只有当numberInt小于等于20时才能正常工作,对于更大的值,整数结果会溢出。 - MAK
今天我制作了一个版本来计算组合,但遇到了一个(显而易见的?)事实,即阶乘在相对较小的输入时会非常快地变得非常大。简单的解决方案是使用System.Numerics.BigInteger而不是任何整数值类型(甚至UInt64)。 - Jack Pines

24

来晚了一点:

Func<int, int> factorial = n => n == 0 ? 1 : 
    Enumerable.Range(1, n).Aggregate((acc, x) => acc * x);

不错的解决方案,但你应该考虑捕获 n = 0 并短路返回 1。 - Dave Lawrence
过度设计吗? :-) - Joris Brauns
1
@JorisBrauns:不完全是这样...它是尾递归的,如果输入的数字足够大,它不会导致堆栈溢出。Wim Ombelets的递归解决方案最终会导致堆栈溢出。 - ebb
@ebb - 感谢分享。我喜欢这种方法,简短而精练。在我的情况下,我传递了委托和整数数组……不需要短路运算也可以正常计算总和……… Func<int[], int> factorial = n => n.Aggregate((acc, x) => acc * x); total = factorial(intArray); - Leo Gurdian
1
它可以工作到12!)) 由于Enumerable.Range(1,n),无法更改为BigInteger - it3xl
1
Enumerable.Range(1, n) .Select(el => (BigInteger)el) .Aggregate((accum, x) => accum*x); 可枚举的范围(1,n) .选择(el =>(BigInteger)el) .聚合((积累,x)=> accum * x); - it3xl

4
您可以使用这个(相当优雅的)解决方案:
    Func<int, int> factorial = null; 
    factorial = x => x <= 1 ? 1 : x * factorial(x-1);
    int numberInt = int.Parse(factorialNumberTextBox.Text);
    factorialAnswerTextBox.Text = factorial(numberInt).ToString();

这并不是一种优雅的解决方案,难以阅读。(我建议只在情况简单易懂时使用三元运算符) - Martin

3
public static int Factorial(int facno)
{
    int temno = 1;

    for (int i = 1; i <= facno; i++)
    {
        temno = temno * i;
    }

    return temno;
}

2

我来晚了,但这里是内容:

    public ulong Factorial(uint numb)
    {
        if (numb <= 1) return 1;
        ulong final = 1;
        for (uint i = 1; i <= numb; i++)
        {
            final *= i;
        }
        return final;
    }

注意:
为了获得更好的范围,我使用了无符号类型。
这个计算可以计算到65的阶乘,而普通有符号类型会给出负数值。

1
试图创建一个更加健壮的n阶乘解决方案。这里的方案考虑了n为负数、零或溢出的情况。使用long类型的结果变量(而不是int)可以计算“更大”的值(对于long,您可以计算n = 20及以下的值)。如果发生溢出,此代码将返回0,但您可以更改它以执行更合适的操作。
    static long nFactorial(int n)
    {
        if (n <= 1)
        {
            return 1;
        }
        long result = 1;
        try
        {
            for (int i = 1; i <= n; i++)
            {
                result = checked(result * i); 
            }
        }
        catch (OverflowException)
        {
            return 0;
        }
        return result;
    }

1

我需要创建一个阶乘方法来计算组合,但是发现当输入相对较小时,阶乘会非常快地变得非常大。这里是我的解决方案,使用 System.Numerics.BigInteger 实现而不使用递归以避免堆栈溢出。

static BigInteger factorial(int num) {
    BigInteger result = 1;
    while (num > 1) {
        result *= num--;
    }
    return result;
}

显然,您也可以使用BigInteger来处理输入,但我的用例是我正在处理int值。

1

使用For循环最简单的方法是:

private static int Fact(int num){
  if (num <= 1){
    return 1;
  }
  int result = 0;
  for(int i = num; i > 1; i--){
    --num; 
    result = (result == 0) ? i-- * num : result * i;
  }
  return result;
}

如果您输入 Fact(3),则 num 将具有值 3。我们将其存储到 i,然后 i = 3,--num 将减少为 2。就像 3 * 2 * 1(基数并将结束循环)。

0
static void Main()
{
    int numberFactorial = int.Parse(Console.ReadLine());
    int result = numberFactorial;

    for (int i = 1; i < numberFactorial; i++)
    {
        result = result * i;
        Console.WriteLine("{0}*{1}",numberFactorial,i);
    }
    Console.WriteLine(result);
}

0

使用阶乘函数:

static long Factorial(long number)
    {
    if( number <= 1 )
        return 1;
    else
        return number * Factorial(number - 1);
    }

然后调用函数:

long result = Factorial(int.Parse(factorialNumberTextBox.Text));
factorialAnswerTextBox.Text = result.ToString();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接