简体   繁体   中英

LINQ Aggregate function is not working properly after 13 factorial?

For my curiosity I am writing a code to find the factorial of large number eg:25. For that I wrote the below code. I use BigInteger as it can store value of any length as define per memory.

int a = 13;
BigInteger factorial1 = a == 0 ? 1 : Enumerable.Range(1, a).Aggregate((i, j) => i * j); // Aggregate function not working properly after 12 factorial

Console.WriteLine(factorial1);

But surprisingly, I don't get the correct answer. I tried for smaller number upto 12 factorial and it gives correct answer but for 13 and beyond, the answer is wrong.

I have tried this very simple code which gives the correct answer.

BigInteger factorial3 = 1;
while (n > 0)
{
    factorial3 = factorial3 * n;
    --n;
}
Console.WriteLine(factorial3);

But the problem here is that BigInteger is immutable. So the above code will have a large memory foot print which is not desirable.

You should specify starting aggregation value, it should be BigInteger.One :

BigInteger factorial1 = a == 0 ? 1 : Enumerable
  .Range(1, a)
  .Aggregate(BigInteger.One, (i, j) => i * j);

otherwise for .Aggregate((i, j) => i * j) the result will be of type int (since both i and j are int ) and only then (after integer overflow , 13. = 6227020800 > int.MaxValue = 2147483647 ) it will be cast to BigInteger .

Enumerable.Range produces int s, not BigInteger s. Enumerable.Range(1, a).Aggregate((i, j) => i * j); uses Int32 throughout and ends up overflowing after 13.

To avoid overflow you need to convert those integers to BigInteger before processing them:

var n=Enumerable.Range(1, 13).Select(i=>(BigInteger)i)
                             .Aggregate((i, j) => i * j);

This produces 6227020800

Another option is to create your own Range method that creates BigInteger values:

public static IEnumerable<BigInteger> BigRange(BigInteger start,int count)
{
    for(var i=start;i<start+count;i++)
    {
        yield return i;
    }
}

...

var n=BigRange(1, 13).Aggregate((i, j) => i * j);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM