Такая вещь, как расчет двигателя для C #? - PullRequest
9 голосов
/ 01 февраля 2011

Существует ли какой-либо механизм вычислений для C #, который может автоматически пересчитывать зависимые поля при изменении значения?

Позвольте мне вольным стилем на секунду, я представляю что-то вроде этого ..

 Field<double> quantity = Field.Create<double>("Quantity");
 Field<double> unitCost = Field.Create<double>("Unit Cost");
 Field<double> total = Field.Create<double>("Total");

 total.Calculation((q,uc) => q * uc, quantity, value);
      // would have signature something like this:
      // void Calculation<TR,T1,T1>(Func<TR,T1,T2>, Field<T1>, Field<T2>)

Это установит поля, которые автоматически распространяют зависимые значения.

 quantity.Value = 5.0;
 unitCost.Value = 1.5;
 Assert.That(total.Value, Is.EqualTo(7.5));

Очевидно, что это простой пример, конечное использование будет гораздо более похожим на вычисления сложной электронной таблицы.

Если подумать, было бы удивительно, если бы поле / ячейки поддерживали уведомление об изменении.

Ответы [ 5 ]

5 голосов
/ 01 февраля 2011

Вы видели http://ncalc.codeplex.com?

Это расширяемое, быстрое (например, имеет свой собственный кэш) позволяет вам предоставлять пользовательские функции и переменные во время выполнения путем обработки событий EvaluateFunction / EvaluateParameter.Примеры выражений, которые он может анализировать:

Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");

  e.Parameters["Pi2"] = new Expression("Pi * Pi");
  e.Parameters["X"] = 10;

  e.EvaluateParameter += delegate(string name, ParameterArgs args)
    {
      if (name == "Pi")
      args.Result = 3.14;
    };

  Debug.Assert(117.07 == e.Evaluate());

Он также обрабатывает Unicode и многие типы данных.Он поставляется с файлом рога, если вы хотите изменить грамматику.Существует также форк, который поддерживает MEF для загрузки новых функций.

Он также поддерживает логические операторы, строки даты / времени и операторы if.

решение

Вы можете выполнить автоматический пересчет, реализовав INotifyPropertyChanged, а затем выполнить что-то вроде

  • , установиввыражение поля this.Field.Expression = new Expression ("Field1 + Field2");

По notifyproperty, обновлен в классе

  • для каждого поля (с отражением), которое является функцией
  • , если его выражение относится к измененному полю, затем пересчитатьпеременная.
  • при пересчете вам нужно обработать событие EvaluateParameter, чтобы использовать отражение, чтобы найти правильное поле и извлечь его значение (вы можете кэшировать, чтобы избежать отражения, если это необходимо)
1 голос
/ 20 декабря 2012

Существуют механизмы вычислений для скалярных параметров, а также механизмы вычислений более высокого уровня для таблиц, обычно используемые для таких приложений, как финансовое планирование, расчеты комиссионных и сборов, расчеты сети и контракта ...

Позвольте мне объяснить это в ближайшее время. Рассмотрим следующие формулы для скаляров:

1) z = f1(x,y)
2) p = f2(z,n)
3) q = f3(x,p)
...

и так далее. Для настройки таких функций и деревьев зависимостей требуется механизм вычислений со скалярными параметрами. Я бы (также) рекомендовал следующую ссылку для такого механизма вычислений, написанного на c #, как хорошую отправную точку: http://www.codeproject.com/Articles/246374/A-Calculation-Engine-for-NET

Как уже упоминалось, существуют также механизмы вычислений с табличными функциями, которые принимают таблицы в качестве параметров. Основной принцип, но тот же:

1) (T4, T5) = TableFunction1(T1, T2, T3)  
2) (T7, T8) = TableFunction2(T2, T4)
...

и т. Д. Обратите внимание, что табличная функция может возвращать несколько таблиц в качестве выходных данных, как показано выше.

Здесь можно наблюдать две ключевые проблемы:

a) Значения таблиц T7 и T8 зависят от таблиц T2 и T4. Поэтому таблицы T7 и T8 необходимо обновлять, выполняя функцию «TableFunction2» только в случае изменения одного из входных параметров T2 или T4.

Аналогично, T4 необходимо обновлять, только если T1, T2 или T3 обновлены; дерево зависимостей!

b) Отделение базы данных от процесса расчета: механизм расчета должен работать независимо от какой-либо фиксированной структуры данных или схемы базы данных, чтобы его можно было интегрировать с любой базой данных и структурой данных.

Вы можете найти мою статью, в которой эти принципы объясняются по адресу:

Логическая архитектура структуры вычислений на основе правил http://finaquant.com/logical-architecture-of-a-rule-based-calculation-framework/1053

Теперь на основе этих принципов разрабатывается библиотека C # / .NET для механизма вычислений с таблицами в качестве входных и выходных параметров.

Примечание для модераторов: пожалуйста, удалите ссылку выше, если она считается саморекламой.

1 голос
/ 06 декабря 2012

Я бы рекомендовал также взглянуть на Джейса.Jace - более современный механизм вычислений для платформы .NET.Это намного быстрее, чем предложенный выше NCalc.Более того, он поддерживает больше платформ (.NET, WinRT, WP7 и WP8).

Более подробную информацию о Jace можно найти на странице GitHub: https://github.com/pieterderycke/Jace

Ссылка NuGet: https://www.nuget.org/packages/Jace

1 голос
/ 02 февраля 2011

Я задавал подобный вопрос здесь: Действительно декларативный язык?

Насколько я знаю, только что услышал о NCalc, я посмотрю на это. У меня есть проект, который делает в значительной степени то, что вы описываете, а затем некоторые, такие как кэширование / сброс кеша при изменении значений или структуры модели. Думайте об этом как о пересечении базы данных и Excel. Вы также можете определить классы и т. Д. И связать их вместе в большие модели с миллионами объектов на графиках, а не только с деревьями. Клиентский сервер и т. Д. Также имеется редактор моделей, в котором вы создаете модели в пользовательском интерфейсе, чтобы вы могли проанализировать, как все расчеты строятся друг на друге.

Почему именно ты спрашиваешь?

0 голосов
/ 11 марта 2018

Одной из проблем эффективности механизма общих правил является пересчет групп сумм и т. Д. Представьте, что вы хотите рассчитать сумму НДС. В вашем счете-фактуре появилось сообщение о том, что какой-то товар изменился, а НДС изменился с одного на другой. Теперь самое простое решение - пересчитать все налоги. Но мы могли бы представить умное решение, которое мы знаем, что в данной группе нам нужно вычесть сумму НДС и добавить ее в другую группу. Другая проблема - циклы. Мы можем потребовать, чтобы наш движок вычислял часть оставшейся суммы для оплаты, когда мы вводим ее в платное поле. А в другом случае мы хотели бы рассчитать оплаченное поле, если мы введем его в оставшееся поле для оплаты. Это можно сделать с помощью виртуального поля «какое поле было введено пользователем» и, если это зависит от правила

...