Action, Func, Predicate - Cause why the sum with double does not work. The override.

Markus Freitag 3,786 Reputation points
2023-09-28T16:06:24.63+00:00

Hello,

The goal is to

Sum of articles, output in double or decimal.

Sum as or for int works well.

Not work!

double test = liste.Sum(getWarenwertDouble);

Trace.WriteLine($"Warenwert-----------{liste.Sum(getWarenwertDouble)}");

Picture try

enter image description here

// This works well too, because is only double, not an object.
List<double> Amount = new List<double>() { 1.0, 2.0, 3.0, 4.0 };
Console.WriteLine(Amount.Sum()); //10
var top3 = Amount.OrderByDescending(x => x).Take(3); // 4.0, 3.0, 2.0



public class Artikel
{
	public string Bezeichnung { set; get; }
	public decimal Preis { set; get; }
	public int Menge { set; get; }

	public override string ToString()
	{
		return Bezeichnung + "|" + Preis + "|" + Menge;
	}
}
	
	
private void btnPredicateActionFunc_Click(object sender, EventArgs e)
{
	List<Artikel> liste = new List<Artikel>();
	liste.Add(new Artikel() { Bezeichnung = "short", Menge = 10, Preis = 99.99m });
	liste.Add(new Artikel() { Bezeichnung = "shirt", Menge = 15, Preis = 78.99m });

	liste.ForEach(getAction);
	Trace.WriteLine("------------");
	liste.ForEach(obj => Trace.WriteLine(obj));
	Trace.WriteLine("------------");
	liste.FindAll(getPredicate).ForEach(getAction);
	Trace.WriteLine("------------");


	Trace.WriteLine($"Warenwert-----------{liste.Sum(getWarenwert)}");


	double test = liste.Sum(getWarenwertDouble);
	Trace.WriteLine($"Warenwert-----------{liste.Sum(getWarenwertDouble)}");
}

public void getAction(Artikel obj)
{
	Trace.WriteLine(obj);
}

public bool getPredicate(Artikel obj)
{
	return obj.Preis < 90;
}

public int getWarenwert(Artikel obj)
{
	return Convert.ToInt32(obj.Preis) * obj.Menge;
}

public double getWarenwertDouble(Artikel obj)
{
	return Convert.ToDouble(obj.Preis) * obj.Menge;
}


C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,922 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 65,211 Reputation points
    2023-09-28T16:32:54.11+00:00

    a double is in base 2, and can not accurately represent decimal numbers. You will get rounding errors as many decimal values are repeating numbers in base 2. similar to 1/3 in decimal.

    https://en.wikipedia.org/wiki/Floating-point_arithmetic#IEEE_754:_floating_point_in_modern_computers

    the decimal datatype uses base 10, so it can accurately represent decimal numbers.

    the standard workaround for handling money in double, is to do the calculation in whole pennies, and divide by 100 or whatever number of decimal places you want. that is use whole number with an implied decimal point.

    try:

    double test = liste.Sum(v => Convert.ToDouble(obj.Preis * 100m) * obj.Menge) / 100.0;
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.