如何计算结果超过Int32.Max值的int数组的总和

时间:2017-01-06 22:21:32

标签: c#

例如,我们有一个int数组:

var array = new int[]{ 2147483647, 2147483647, 2147483647, 2147483647};

计算数组条目总和的最简单方法是什么,但就上面提供的示例而言

array.Sum()

结果:

  

算术运算导致溢出

因为结果不再是int ..

3 个答案:

答案 0 :(得分:11)

因为数组中的值总和溢出Int32.MaxValue,您将被迫将元素强制转换为长

var array = new int[]{ 2147483647, 2147483647, 2147483647, 2147483647};
var total = array.Sum(x => (long)x);
Console.WriteLine(total);

您可以看到总变量的类型为Int64

Console.WriteLine(total.GetType());

答案 1 :(得分:6)

史蒂夫的回答非常适合你的问题。但是,如果您需要存储长度超过典型数据类型的值的总和,则可以使用BigInteger

var array = new [] { long.MaxValue, long.MaxValue, long.MaxValue, long.MaxValue };
var result = new BigInteger();
result = array.Aggregate(result, (current, i) => current + i);

此解决方案也适用于您提供的阵列。

答案 2 :(得分:1)

要扩展Steve的“如何求和一个超出Int64.MaxValue的long []数组?”的解决方案,可以使用十进制类型对long []的数组求和,如下:

class Foo<T>(val n: Int) {
    // How to make this int[]?
    // Or IntArray?
    lateinit var data: Any

    inline fun <reified T> createNullArray() {
        data = arrayOfNulls<T>(n)
    }
}

十进制数有一个96位尾数,这足以实现其中2 Giga长的数组的精确结果,这是C#中数组的最大大小,这是因为数组索引限制为Int32。使用上述十进制实现比使用BigInteger快5倍。

走得更快:

class Foo(val n: Int) {
    lateinit var data: Any
    inline fun <reified T> createNullArray() {
        data = arrayOfNulls<T>(n)
    }
}

该解决方案利用多核CPU的优势来提高性能。

为了更快,HPCsharp nuget包使用数据并行SSE指令为int [],uint [],long [],ulong []和所有其他有符号和无符号整数类型实现了Sum()单核以及并行多核的性能,而每种数据类型的总和都超过了MaxValue。