我想用linq填充阶乘列表。我知道了,这能撑到12。我想这是因为整数范围。但我没法重打一遍。这可以很容易地修改(重打)吗?
var listOfFactorials = from fact in Enumerable.Range(0, 171).Reverse().ToList() select new { Number = fact, Factorial = (fact == 0) ? 1d : Enumerable.Range(1, fact).Aggregate((i, j) => (i * j))};
我想用阶乘填充这个列表直到数字170。我不需要它做任何事情,只是为了好玩:)
必须使用BigInteger:
var listOfFactorials = from fact in Enumerable.Range(0, 200).Reverse().ToList()
select new
{
Number = fact,
Factorial = (fact == 0) ? BigInteger.One : Enumerable.Range(1, fact)
.Select( i => new BigInteger(i))
.Aggregate((i, j) => (i * j))
};
您不需要double
-它只给您15位精度以换取更大的范围。您想使用long
或BigInteger
。
您可以在调用Aggregate
之前转换从Range
返回的整数:
Enumerable.Range(1, fact)
.Select(i => new BigInteger(i))
.Aggregate((i, j) => (i * j))};
或者使用更详细的Aggregate
版本,分别指定类型:
Enumerable.Range(1, fact)
.Aggregate<int, BigInteger>(new BigInteger(1), (i, j) => (i * j))
注意Long会在67!
溢出,而BigInteger
理论上是无界的
请注意,您的Aggregate
不是很有效,因为它每次都从1重新计算到n,如果您从1开始,您只能对每个后续值执行一次倍数:
var listOfFactorials = Enumerable.Range(1, 170)
.Aggregate(new[] { new { Number = 0, Factorial = BigInteger.One } }.ToList(),
(ans, n) => { ans.Add(new { Number = n, Factorial = ans.Last().Factorial * n }); return ans; })
.AsEnumerable()
.Reverse();
由于序列是用0
值初始化的,所以少一个值的范围必须从1
开始。
一个更简单(可能更容易理解)的方法是使用for
循环:
var ans = new[] { new { Number = 0, Factorial = BigInteger.One } }.ToList();
var Factorial = BigInteger.One;
for (int Number = 1; Number < 171; ++Number) {
Factorial *= Number;
ans.Add(new { Number, Factorial });
}
ans.Reverse();