0

Linq group by is showing wrong mathematical results. I have tried to extract & minimize the code to the point.

public class ModelBO
{
     public string Code { get; set; }
     public double Amt { get; set; }
}


List<ModelBO> list = new List<ModelBO>();
list.Add(new ModelBO { Code = "A2", Amt = 0.97 });
list.Add(new ModelBO { Code = "A2", Amt = -3.36 });
list.Add(new ModelBO { Code = "A2", Amt = -0.01 });
list.Add(new ModelBO { Code = "A2", Amt = 1.42 });
list.Add(new ModelBO { Code = "A2", Amt = -0.01 });
list.Add(new ModelBO { Code = "A2", Amt = 0.03 });
list.Add(new ModelBO { Code = "A2", Amt = -0.14 });
list.Add(new ModelBO { Code = "A2", Amt = -0.02 });
list.Add(new ModelBO { Code = "A2", Amt = -0.05 });
list.Add(new ModelBO { Code = "A2", Amt = 0.03 });
list.Add(new ModelBO { Code = "A2", Amt = 0.06 });
list.Add(new ModelBO { Code = "A2", Amt = 0.01 });
list.Add(new ModelBO { Code = "A2", Amt = 0.51 });
list.Add(new ModelBO { Code = "A2", Amt = 0.29 });
list.Add(new ModelBO { Code = "A2", Amt = -0.67 });
list.Add(new ModelBO { Code = "A2", Amt = 0.02 });
list.Add(new ModelBO { Code = "A2", Amt = 0.08 });
list.Add(new ModelBO { Code = "A2", Amt = 0.09 });
list.Add(new ModelBO { Code = "A2", Amt = 0.37 });
list.Add(new ModelBO { Code = "A2", Amt = 0.17 });
list.Add(new ModelBO { Code = "A2", Amt = 0.21 });

List<ModelBO> t = list.GroupBy(x => new { x.Code }).Select(g => new ModelBO { Code = g.Key.Code, Amt = g.Sum(x => x.Amt) }).ToList();

Now, in results, t[0].Amt should be zero. But, I am getting different result. What must be wrong here.

Jay
  • 408
  • 2
  • 6
  • 27
  • Why do you group by `new { x.Code }` and not just `x.Code`? – ProgrammingLlama May 18 '20 at 07:47
  • In real example I am grouping by total 7 columns – Jay May 18 '20 at 07:49
  • If you got something like `2.2204460492503131E-16`, you may round a result. It happens due to internal representation of double and float numbers – Pavel Anikhouski May 18 '20 at 07:49
  • @PavelAnikhouski yes, I get that result. I did try to round it off. Let me try again – Jay May 18 '20 at 07:50
  • @jay `Amt = Math.Round(g.Sum(x => x.Amt), 2)` should work fine – Pavel Anikhouski May 18 '20 at 07:50
  • I see. Anyway, in binary it's only possible to accurately represent fractions formed of 1/2n (e.g. 1/2, 1/4, 3/4, etc.), so fraction combinations outside of that, combined with the limited precision of floating point values, means that you'll lose some information in situations like this. If you're dealing with money, you should use `decimal` instead of `double`. – ProgrammingLlama May 18 '20 at 07:52
  • 1
    @John yes, I am dealing with invoice amount here. I will use decimal. Thanks for suggestion. – Jay May 18 '20 at 07:53

0 Answers0