Получить среднее значение в секунду. Как это сделать более правильно? Здравствуйте. Мне нужно рассчитать среднее значение полученных данных в секунду. Например, есть класс:class StateMonitor { private long _quantityOfValues; private long _quantityOfCalls; private readonly object _quantityOfValuesSync = new object(); private readonly object _frequencySync = new object(); public void Increment() { lock (_quantityOfValuesSync) { ++_quantityOfValues; } } public int Frequency { get { long quantityOfValues; lock (_quantityOfValuesSync) { quantityOfValues = _quantityOfValues; } lock (_frequencySync) { double result = (double)quantityOfValues / ++_quantityOfCalls; result = Math.Round(result, MidpointRounding.AwayFromZero); return (int)result; } } } } Чтобы он правильно считал частоту вызова метода Increment в секунду нужно вызывать свойство Frequency 1 раз в секунду. Что нельзя назвать удобным и надёжным. Наверняка есть формула для такого подсчёта. Догадываюсь, что нужно будет сохранять время последнего вызова свойства Frequency, чтобы правильно считать. Чёт никак не допетрю, как же правильно считать? Вот код для теста класса выше:using System; using System.Threading; using System.Threading.Tasks; namespace FrequencyReceivingTest2 { internal class Program { #region Entry point private static Program _program; private static void Main(string[] args) { _program = new Program(); _program.Run(args); } #endregion private void Run(string[] args) { var monitor = new StateMonitor(); int counter = 0; Task[] tasks = { new Task(() =>
{ while (counter++ { while (counter task.Start()); Task.WaitAll(tasks); Console.WriteLine("Конец."); Console.ReadKey(); } } }
Для более надежного и удобного подсчета среднего значения в секунду можно внести некоторые изменения в класс StateMonitor.
Одним из способов сделать это является добавление поля для сохранения времени последнего вызова метода Increment и изменение метода Frequency для учета временного интервала между вызовами.
Вот пример модифицированного класса StateMonitor:
class StateMonitor { private long _quantityOfValues; private long _quantityOfCalls; private DateTime _lastUpdate; private readonly object _quantityOfValuesSync = new object(); private readonly object _frequencySync = new object(); public void Increment() { lock (_quantityOfValuesSync) { ++_quantityOfValues; } } public int Frequency { get { DateTime now = DateTime.Now; lock (_quantityOfValuesSync) { double timeElapsed = (now - _lastUpdate).TotalSeconds; if (timeElapsed > 0) { double result = (double)_quantityOfValues / timeElapsed; return (int)Math.Round(result, MidpointRounding.AwayFromZero); } else { return 0; } } } } public void UpdateLastUpdate() { _lastUpdate = DateTime.Now; ++_quantityOfCalls; } }
В методе Increment можно добавить вызов метода UpdateLastUpdate для обновления времени последнего вызова. А метод Frequency теперь учитывает временной интервал между вызовами, что позволит более точно рассчитать среднее значение в секунду.
Теперь в методе Main можно вызывать UpdateLastUpdate после каждого вызова Increment:
new Task(() => { while (counter++ < 20) { int ms = 0; while (ms < 1000) { const int WaitMs = 200; monitor.Increment(); monitor.UpdateLastUpdate(); Thread.Sleep(WaitMs); ms += WaitMs; } } }),
Эти изменения позволят более надежно и удобно рассчитывать среднее значение в секунду на основе полученных данных.
Для более надежного и удобного подсчета среднего значения в секунду можно внести некоторые изменения в класс StateMonitor.
Одним из способов сделать это является добавление поля для сохранения времени последнего вызова метода Increment и изменение метода Frequency для учета временного интервала между вызовами.
Вот пример модифицированного класса StateMonitor:
class StateMonitor{
private long _quantityOfValues;
private long _quantityOfCalls;
private DateTime _lastUpdate;
private readonly object _quantityOfValuesSync = new object();
private readonly object _frequencySync = new object();
public void Increment()
{
lock (_quantityOfValuesSync)
{
++_quantityOfValues;
}
}
public int Frequency
{
get
{
DateTime now = DateTime.Now;
lock (_quantityOfValuesSync)
{
double timeElapsed = (now - _lastUpdate).TotalSeconds;
if (timeElapsed > 0)
{
double result = (double)_quantityOfValues / timeElapsed;
return (int)Math.Round(result, MidpointRounding.AwayFromZero);
}
else
{
return 0;
}
}
}
}
public void UpdateLastUpdate()
{
_lastUpdate = DateTime.Now;
++_quantityOfCalls;
}
}
В методе Increment можно добавить вызов метода UpdateLastUpdate для обновления времени последнего вызова. А метод Frequency теперь учитывает временной интервал между вызовами, что позволит более точно рассчитать среднее значение в секунду.
Теперь в методе Main можно вызывать UpdateLastUpdate после каждого вызова Increment:
new Task(() =>{
while (counter++ < 20)
{
int ms = 0;
while (ms < 1000)
{
const int WaitMs = 200;
monitor.Increment();
monitor.UpdateLastUpdate();
Thread.Sleep(WaitMs);
ms += WaitMs;
}
}
}),
Эти изменения позволят более надежно и удобно рассчитывать среднее значение в секунду на основе полученных данных.