This repository has been archived by the owner on May 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathWeightedAvg.cs
158 lines (143 loc) · 4.47 KB
/
WeightedAvg.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
namespace RCNet.MathTools
{
/// <summary>
/// Implements the weighted average.
/// </summary>
[Serializable]
public class WeightedAvg
{
//Attribute properties
/// <summary>
/// The number of samples.
/// </summary>
public int NumOfSamples { get; private set; }
/// <summary>
/// The sum of samples.
/// </summary>
public double SumOfSamples { get; private set; }
/// <summary>
/// The sum of weights.
/// </summary>
public double SumOfWeights { get; private set; }
/// <summary>
/// The computed weighted average.
/// </summary>
public double Result { get; private set; }
//Constructors
/// <summary>
/// Creates an unitialized instance.
/// </summary>
public WeightedAvg()
{
Reset();
return;
}
/// <summary>
/// The copy constructor.
/// </summary>
/// <param name="source">The source instance.</param>
public WeightedAvg(WeightedAvg source)
{
Adopt(source);
return;
}
//Methods
/// <summary>
/// Computes the resulting weighted average.
/// </summary>
private double Compute()
{
if (SumOfWeights != 0 && NumOfSamples > 0)
{
Result = SumOfSamples / SumOfWeights;
}
else
{
Result = 0;
}
return Result;
}
/// <summary>
/// Creates the deep copy of this instance.
/// </summary>
public WeightedAvg DeepClone()
{
return new WeightedAvg(this);
}
/// <summary>
/// Resets the instance.
/// </summary>
public void Reset()
{
SumOfSamples = 0;
SumOfWeights = 0;
Result = 0;
NumOfSamples = 0;
return;
}
/// <summary>
/// Adopts the data from source instance.
/// </summary>
/// <param name="source">The source instance.</param>
public void Adopt(WeightedAvg source)
{
SumOfSamples = source.SumOfSamples;
SumOfWeights = source.SumOfWeights;
Result = source.Result;
NumOfSamples = source.NumOfSamples;
return;
}
/// <summary>
/// Adds the next sample value and its weight into the weighted average.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="weight">The value weight.</param>
/// <returns>The resulting weighted average.</returns>
public double AddSample(double value, double weight = 1d)
{
SumOfSamples += value * weight;
SumOfWeights += weight;
++NumOfSamples;
return Compute();
}
/// <summary>
/// Removes the sample value and its weight from the weighted average.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="weight">The value weight.</param>
/// <returns>The resulting weighted average.</returns>
public double RemoveSample(double value, double weight = 1)
{
if (NumOfSamples > 0)
{
SumOfSamples -= value * weight;
SumOfWeights -= weight;
--NumOfSamples;
if (NumOfSamples == 0)
{
SumOfSamples = 0;
SumOfWeights = 0;
}
}
else
{
throw new InvalidOperationException($"Can't remove the sample because there is no samples.");
}
return Compute();
}
/// <summary>
/// Computes the weighted average for the next hypothetical sample.
/// </summary>
/// <remarks>
/// Operation does not change the instance data.
/// </remarks>
/// <param name="simValue">The next sample value.</param>
/// <param name="simWeight">The next sample value weight.</param>
/// <returns>The resulting weighted average.</returns>
public double SimulateNext(double simValue, double simWeight = 1)
{
return (SumOfSamples + (simValue * simWeight)) / (SumOfWeights + simWeight);
}
}//WeightedAvg
}//Namespace