LoginSignup
0
0

More than 5 years have passed since last update.

【LINQ】Sum()でOverFlowExceptionが発生

Last updated at Posted at 2018-10-31

LINQのSum()はOverFlowExceptionが発生することが有りますので、doubleやdecimalなど適切な範囲を持つ数値型を使いましょう、というお話。

var testList1 = new List<int>() { 1, 2147483647 };
//Sumでは型の範囲を超えるとOverflowExceptionが発生
//var sum = testList1.Sum();
//Console.WriteLine("sum = " + sum);

//AggregateすればOverflowExceptionは発生しない。
var aggregate = testList1.Aggregate((sum1, sum2) => sum1 + sum2);
//但し、aggregate = -2147483648になってしまう。
Console.WriteLine("aggregate = " + aggregate); 

var doubleSum = testList1.Select(a => (double)a).Sum();
Console.WriteLine("doubleSum = " + doubleSum);//期待通りdoubleSum = 2147483648

var decimalSum = testList1.Select(a => (decimal)a).Sum();
Console.WriteLine("decimalSum = " + decimalSum);//期待通りdecimalSum = 2147483648

事の発端はOpenCVSharpでcontour(OpenCVSharp.Point[])の座標計算でした。
以下の計算をしたところOverFlowExceptionが発生しました。

List<OpenCvSharp.Point> points = GetPoints();
//OverFlowExceptionが発生
points.Select(p => p.X * p.X * p.X - p.X * p.Y * p.Y).Sum();

上のコードは以下数式を演算しようとしました。

\sum_{i=1}^{n}(x_i^3 - x_iy_i^2)

OpenCVSharp.PointのXとYはint型の為、上の計算をintで実行してOverFlowExceptionが発生しました。
渡したパラメータがたまたまintの桁あふれが起きる値で気付けました。
こういった計算で意識せずに桁あふれとか怖いですね。


List<OpenCvSharp.Point> points = GetPoints();
//計算結果が欲しいだけなら
var total = points.Select(p => (double)p.X * (double)p.X * (double)p.X - (double)p.X * (double)p.Y * (double)p.Y).Sum();

//そもそも演算中はdouble型のPoint2dを使ったほうがいいのでは
var toDouble = points.Select(a => new OpenCvSharp.Point2d(a.X,a.Y);

これとかこれは似たような悩みでしょうか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0