我有一个方法,使用类似于此的方法汇总一组十进制值...
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
在实际代码中,金额集合中通常有更多成员,并且至少有50个单独的金额集合需要在总操作中求和。
经常调用总量的重新计算(至少一次,然后再次针对每个集合内容更改),并且在配置文件跟踪中显示占总操作时间的2-5%。我希望看看是否有人知道如何加快这个求和操作,或者这是否是最快的。
在这种情况下缓存是不现实的,因为必须重新计算必须的金额。
****编辑** 对于Ravadre和Joel - 总金额存储在类级别(每个金额集合和总和都包含在类实例中)
有什么想法吗?
答案 0 :(得分:3)
尝试继承List(Of Decimal),公开TotalSum属性。每次调用Add()时,都会按照插入的值递增。这将使您不必遍历列表以获得总和。
编辑: 尝试之后,最好实现IList(Of Decimal),因为List的方法不是虚拟的。有点像这样的(是的,我知道它是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; }
}
}
答案 1 :(得分:2)
我不清楚您希望如何比依次添加每个数字更快地添加数字列表!
但是,使用decimal
进行算术运算可能比使用浮点类型慢得多,所以如果你实际上不需要精度,我建议切换。
答案 2 :(得分:2)
如果这些是货币值,请考虑使用缩放整数。 对于2位小数,您存储的是便士数而不是美元数,然后在需要输出结果时除以100。 对于5位小数,您的变量在内部使用原始数字* 100000。 这应该会提高性能和准确性,尤其是在进行任何划分时。
答案 3 :(得分:1)
totalAmount = amountCollection.Sum()
怎么样?
答案 4 :(得分:1)
至少有50个单独的金额集合需要在总操作中求和。
如何缓存每个系列的总和?然后,当集合发生变化时,您只需要总结该集合和缓存的总计。
答案 5 :(得分:1)
总分析跟踪时间的2-5%并不是那么多。
即使您将此方法的执行时间缩短了一半,您最多也可以节省总运行时间的百分之几。
你最好的选择可能是先到别处去看看。
答案 6 :(得分:0)
考虑到你使用的是List(Of T)
,事情的速度和它一样快。
其他人建议您使用Sum
扩展方法 - 这将不提高性能,因为其实现与您当前解决问题的方法相同:
<Extension> _
Public Shared Function Sum(ByVal source As IEnumerable(Of Decimal)) As Decimal
If (source Is Nothing) Then
Throw Error.ArgumentNull("source")
End If
Dim num As Decimal = 0
Dim num2 As Decimal
For Each num2 In source
num = (num + num2)
Next
Return num
End Function
答案 7 :(得分:0)
你的另一种选择是使用for循环,你不必创建一个枚举器,但实际上并没有显着的提升(据我所知)。
为什么你不能缓存结果?如果缓存总数量,并且对于其中一个元素的每次更改,请使用相同的值修改数量(并最终计算所有每个10个修改以进行同步)。因此,当其中一个元素从2.5更改为3.6时,您只需将1.1添加到总金额中。为什么这不适用于您的情况?
答案 8 :(得分:0)
如果你不想实现IList / IDictionary的版本,因为statenjason建议你可以创建一个包装器:
Public Class TotalDictionaryWrapper
Private innerDictionary As IDictionary(Of Integer, Decimal)
Private m_total As Decimal = 0D
Public Sub New(ByVal dictionary As IDictionary(Of Integer, Decimal))
Me.innerDictionary = dictionary
End Sub
Public ReadOnly Property Total() As [Decimal]
Get
Return Me.m_total
End Get
End Property
Public Sub Add(ByVal key As Integer, ByVal value As Decimal)
Me.innerDictionary.Add(key, value)
m_total += value
End Sub
Public Sub Remove(ByVal key As String)
Dim toRemove As Decimal = Me.innerDictionary(key)
Me.innerDictionary.Remove(key)
Me.m_total -= toRemove
End Sub
Public Sub Update(ByVal key As Integer, ByVal newValue As Decimal)
Dim oldValue As Decimal = Me.innerDictionary(key)
Me.innerDictionary(key) = newValue
Me.m_total -= oldValue
Me.m_total += newValue
End Sub
Other methods..
End Class