Улучшена производительность расчета скользящего среднего. IEnumerable против списка, foreach против for, ElementAt,C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Улучшена производительность расчета скользящего среднего. IEnumerable против списка, foreach против for, ElementAt,

Сообщение Anonymous »

Я создал класс для расчета экспоненциальной скользящей средней:

Код: Выделить всё

public class ExponentialMovingAverage {

public Int32 Period { get; set; }

public ExponentialMovingAverage(Int32 period = 20) {

ArgumentOutOfRangeException.ThrowIfNegativeOrZero(period);

Period = period;

}

public override IEnumerable Compute(IEnumerable inputs) {

ArgumentNullException.ThrowIfNull(inputs);

inputs = inputs.OrderBy(x => x.Stamp);

Decimal? previous = null;

Decimal factor = (Decimal)(2d / (Period + 1));

Decimal? sum = 0;

Int32 notNulls = 0;

for (Int32 index = 0; index < inputs.Count(); index++) {

(DateTimeOffset stamp, Decimal? value) = inputs.ElementAt(index);

if (value == null) {
notNulls++;
yield return (stamp, null);
continue;
}

if (index < notNulls + Period - 1) {
sum += value;
yield return (stamp, null);
continue;
}

if (index == notNulls + Period - 1) {
sum += value;
Decimal? sma = sum / Period;
previous = sma;
yield return (stamp, sma);
continue;
}

Decimal? ema = previous + (factor * (value - previous));
previous = ema;
yield return (stamp, ema);

}

}

}
И у меня есть следующие тесты, которые проходят:

Код: Выделить всё

[Fact]
public void Test_AllNonNullInputs() {
var ema = new ExponentialMovingAverage(3);

var inputs = new List {
(new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero), 10),
(new DateTimeOffset(2024, 1, 2, 0, 0, 0, TimeSpan.Zero), 15),
(new DateTimeOffset(2024, 1, 3, 0, 0, 0, TimeSpan.Zero), 20),
(new DateTimeOffset(2024, 1, 4, 0, 0, 0, TimeSpan.Zero), 25),
(new DateTimeOffset(2024, 1, 5, 0, 0, 0, TimeSpan.Zero), 30),
(new DateTimeOffset(2024, 1, 6, 0, 0, 0, TimeSpan.Zero), 35)
};
var output = ema.Compute(inputs).ToList();

Assert.Equal(6, output.Count);
Assert.Null(output[0].ExponentialMovingAverage);
Assert.Null(output[1].ExponentialMovingAverage);
Assert.Equal(15m, output[2].ExponentialMovingAverage);
Assert.Equal(20m, output[3].ExponentialMovingAverage);
Assert.Equal(25m, output[4].ExponentialMovingAverage);
Assert.Equal(30m, output[5].ExponentialMovingAverage);
}

[Fact]
public void Test_FirstTwoInputsAreNull() {
var ema = new ExponentialMovingAverage(3);

var inputs = new List {
(new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero), null),
(new DateTimeOffset(2024, 1, 2, 0, 0, 0, TimeSpan.Zero), null),
(new DateTimeOffset(2024, 1, 3, 0, 0, 0, TimeSpan.Zero), 20),
(new DateTimeOffset(2024, 1, 4, 0, 0, 0, TimeSpan.Zero), 25),
(new DateTimeOffset(2024, 1, 5, 0, 0, 0, TimeSpan.Zero), 30),
(new DateTimeOffset(2024, 1, 6, 0, 0, 0, TimeSpan.Zero), 35)
};
var output = ema.Compute(inputs).ToList();

Assert.Equal(6, output.Count);
Assert.Null(output[0].ExponentialMovingAverage);
Assert.Null(output[1].ExponentialMovingAverage);
Assert.Null(output[2].ExponentialMovingAverage);
Assert.Null(output[3].ExponentialMovingAverage);
Assert.Equal(25m, output[4].ExponentialMovingAverage);
Assert.Equal(30m, output[5].ExponentialMovingAverage);
}
Вычисление кажется медленным, например, при расчете EMA для EMA со многими входными данными:

Код: Выделить всё

var ema1 = new ExponentialMovingAverage(3);
var outputs1 = ema1.Compute(inputs);
var ema2 = new ExponentialMovingAverage(3);
var outputs2 = ema2.Compute(ema1);
Я рассматривал использование inputs.ElementAt(index), а также использование foreach vs for и List vs Enumerable.
Как я могу улучшить код, в том числе его производительность?

Подробнее здесь: https://stackoverflow.com/questions/784 ... st-foreach
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Улучшена производительность расчета скользящего среднего. IEnumerable против списка, foreach против for, ElementAt,
    Anonymous » » в форуме C#
    0 Ответы
    65 Просмотры
    Последнее сообщение Anonymous
  • Использование пандов для расчета среднего декабрьского января-февраля среднего
    Anonymous » » в форуме Python
    0 Ответы
    4 Просмотры
    Последнее сообщение Anonymous
  • C# IEnumerable.ElementAt() неожиданно действует на OrderedEnumerable
    Anonymous » » в форуме C#
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous
  • C# IEnumerable.ElementAt() неожиданно действует на OrderedEnumerable
    Anonymous » » в форуме C#
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous
  • C# IEnumerable.ElementAt() неожиданно действует на OrderedEnumerable
    Anonymous » » в форуме C#
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»