Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net - Fastest way to sum a collection of numeric values

I have a method which summarizes a collection of decimal values using a method similar to this...

Dim _amountCollection as New List(Of Decimal)
_amountCollection.Add(145.12D)
_amountCollection.Add(11.32D)
_amountCollection.Add(6547.07D)

Dim _totalAmount as Decimal

For Each _individualAmount as Decimal in _amountCollection
  _totalAmount += _individualAmount
Next 

In the actual code, there are usually more members in the amount collection, and there are at least 50 individual amount collections that need to be summed in a total operation.

This recalculation of total amount gets called often (at least once, and then again for each collection content change), and is showing up in profile traces as consuming between 2-5% of the total operation time. I am looking to see if anyone has an idea of how to speed this summation operation up, or if this is just the fastest its going to get.

Caching is not realistic in this case, because the amounts must be recalculated.

****EDIT** For Ravadre and Joel - The total amount is stored at the class level (each amount collection and sum are contained in a class instance)

Any ideas?

like image 689
StingyJack Avatar asked Dec 28 '25 22:12

StingyJack


2 Answers

Try subclassing List(Of Decimal), expose a TotalSum property. Each time Add() is called, increment by the insterted value. That'll keep you from having to iterate through the list to get the sum.

Edit: After trying, it would be better to implement IList(Of Decimal) because List's methods not being virtual. Something along the lines of this (Yes, I know it's C#...)

public class DecimalSumList : IList<decimal>
{
    readonly IList<decimal> _allValues = new List<decimal>();
    decimal _totalSum;
    public decimal TotalSum { get { return _totalSum; } }
    public void Add(decimal item)
    {
        _totalSum += item;
        _allValues.Add(item);
    }

    public void CopyTo(decimal[] array, int arrayIndex)
    {
        _allValues.CopyTo(array, arrayIndex);
    }

    bool ICollection<decimal>.Remove(decimal item)
    {
        _totalSum -= item;
        return _allValues.Remove(item);
    }

    public int Count
    {
        get { return _allValues.Count; }
    }

    public bool IsReadOnly
    {
        get { throw new NotImplementedException(); }
    }

    public void Remove(decimal item)
    {
        _totalSum -= item;
        _allValues.Remove(item);
    }
    public void Clear()
    {
        _totalSum = 0;
        _allValues.Clear();
    }

    public bool Contains(decimal item)
    {
        return _allValues.Contains(item);
    }

    public IEnumerator<decimal> GetEnumerator()
    {
        return _allValues.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public int IndexOf(decimal item)
    {
        return _allValues.IndexOf(item);
    }

    public void Insert(int index, decimal item)
    {
        _totalSum += item;
        _allValues.Insert(index,item);
    }

    public void RemoveAt(int index)
    {
        _totalSum -= _allValues[index];
        _allValues.RemoveAt(index);
    }

    public decimal this[int index]
    {
        get { return _allValues[index]; }
        set { _allValues[index] = value; }
    }
}
like image 57
statenjason Avatar answered Dec 31 '25 15:12

statenjason


It's not clear to me how you expect to add up a list of numbers faster than adding each one in turn!

However, using decimals to do arithmetic is probably much, much, much slower than using a floating-point type, so if you don't actually need the precision, I suggest switching.

like image 38
mqp Avatar answered Dec 31 '25 14:12

mqp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!