【问题标题】:Array.Sum() results in an overflowArray.Sum() 导致溢出
【发布时间】:2018-10-31 02:42:48
【问题描述】:

我有一个这样的 int 数组

int[] arr = {256741038,623958417,467905213,714532089,938071625};

然后我创建了一个 int64 var

Int64 sum = arr.Sum();

但这导致溢出

运行时异常(第 19 行):算术运算导致 溢出。

如何在不使用循环总结的情况下解决这个问题? (数组类型必须是int)

【问题讨论】:

  • arr.Select(z => (long)z).Sum()
  • @vdthe 这里要理解的关键是Sum 不会根据存储Sum 所需的内容来选择返回类型(在这种情况下是@987654327 @)。相反,它根据被求和的可枚举的类型来选择它。您正在对 int 求和,所以,唉,它尝试(未成功)将总和放入 int

标签: c# arrays sum int overflow


【解决方案1】:

问题在于,虽然单个值适合 int,但这些数字的总和大于 int 可以容纳的结果。

因此,您需要将值转换为 long(或其他需要这么大数字的数据类型,但由于您使用的是 Int64...):

long sum = arr.Sum(v => (long)v);

【讨论】:

    【解决方案2】:

    您必须将其转换为 long 以免溢出

    var result = arr.Select(x => (long)x).Sum();
    

    int (C# Reference)

    范围 = -2,147,483,6482,147,483,647

    一些背景,这是Sum的源码

    public static int Sum(this IEnumerable<int> source) 
    {
          if (source == null) throw Error.ArgumentNull("source");
          int sum = 0;
          checked 
          {
              foreach (int v in source) 
                 sum += v;
          }
          return sum;
    }
    

    意思是,不管你喜不喜欢,有人在使用 for 循环,另外checked 的使用是它抛出的原因:)

    checked (C# Reference)

    checked 关键字用于显式启用溢出检查 整数类型的算术运算和转换。

    【讨论】:

      【解决方案3】:

      当您对整数数组调用 sum 时,输出类型为整数,输入数字的总和大于整数最大值。正如@TheGeneral 所说的 sum 方法检查溢出并抛出异常。

      可能你期望 sum 方法返回结果一样长,但它的返回类型是整数。

      int a = 256741038;
      int b = 623958417;
      int c = 467905213;
      int d = 714532089;
      int e = 938071625;
      
      long sumInt = a + b + c + d + e;
      //-1293758914 //overflow happened withoud exception
      long sumLong = (long)a + b + c + d + e;//clr now the result may be more than int.maxvalue
      //3001208382
      

      【讨论】:

        【解决方案4】:

        你可以找到如下图所示的总和

        using System;
        
        public class Program
        {
            public static void Main()
            {
                Console.WriteLine("Hello World");
                int[] arr = {999999999, 999999999, 999999999,999999999, 999999999};
                 long sum = 0;
                 for (int i = 0; i < arr.Length; i += 1)
                 {
                   sum += arr[i];
                 }
                Console.WriteLine(sum);
            }
        }
        

        Datatype and Range Reference

        【讨论】:

        • 谢谢,但在我的问题中,我说我不想使用任何类型的循环 :) @John 的解决方案非常棒
        【解决方案5】:

        更短的方式如下图所示

        using System;
        namespace Test
        {
            public partial class TestPage : System.Web.UI.Page
            {
                public int[] p = { 999999999, 999999999, 999999999, 999999999, 999999999 };
                protected void Page_Load(object sender, EventArgs e)
                {
                    long s = Sum;
                }
                public long Sum
                {
                    get { long s = 0; Array.ForEach(p, delegate (int i) { s += i; }); return s; }
                }        
            }
        }
        

        希望这会对你有所帮助。

        【讨论】:

        • 谢谢,但在我的问题中我说我不想使用任何类型的循环:)
        • 没有问题我能理解,并且已经通过另一种方式给出了另一个答案,所以我不能重复,但有人可以从你的问题和不同的方式中得到帮助......谢谢,欢迎
        猜你喜欢
        • 2019-10-11
        • 2015-05-21
        • 2014-02-14
        • 2016-09-12
        • 2011-10-31
        • 2020-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多