列表总和太大,引发溢出异常

时间:2018-10-03 18:01:14

标签: c# .net linq math integer-overflow

我有一个最多2000000的质数列表。该列表包含将近150000个非常大的整数。我想要其中所有数字的总和。这是一个随机的大整数列表,仅供演示:

List<int> numbers = new List<int>();
for (int i = 0; i < 100; i++)
{
    numbers.Add(1000000000);
}
Console.WriteLine(numbers.Sum().ToString());

我收到“算术运算导致溢出”异常。我猜想总和太大,但是将其转换为Int64并没有帮助,它仍然会引发相同的异常。

Console.WriteLine(Convert.ToUInt64(numbers.Sum()).ToString());

我什至尝试将总和保存到Int64变量中,然后使用它,但这也不起作用。

long sum = numbers.Sum();
Console.WriteLine(sum.ToString());

是否有可以容纳这么多数字的数据类型,还是我在其他地方犯了错误?感谢您的帮助。

4 个答案:

答案 0 :(得分:8)

在获取总和之前尝试转换为Int64(长整数):

Console.WriteLine(numbers.Select(x=> (long)x).Sum().ToString());

答案 1 :(得分:5)

问题是您的答案超过26.5亿。 将int更改为Int64

List<Int64> numbers = new List<Int64>();
for (int i = 0; i < 100; i++)
{
    numbers.Add(1000000000);
}
Console.WriteLine(numbers.Sum().ToString());

澄清一个Int的最大价值约为26.5亿,而Int64则以万亿为单位

答案 2 :(得分:2)

您可以使用Aggregate方法:

Console.WriteLine(numbers.Aggregate(0L, (c, n) => c + n));

Aggregate的重载将累加器作为第一个参数
文字0L将被视为long,而不是int。这样可以避免算术溢出

答案 3 :(得分:1)

从 int 到 long 的转换很便宜,有时甚至是免费的。让我们比较五个代码

long sum = intArr.Select(x => (long)x).Sum(); // 0.95s

long sum = intArr.Sum(x => (long)x); // 0.95s

long sum = longArr.Sum(); // 0.86s

long sum = 0;
foreach (int x in intArr)
{
    sum += x; // 0.22s
}

long sum = 0;
foreach (long x in longArr)
{
    sum += x; // 0.23s
}

已用时间用于 100M 项。如您所见,如果您关心性能,则转换不是问题