Подтвердить что ты не робот

Создание динамической формулы

Мне нужно создать ui, чтобы пользователь создал формулу. т.е.:

Для одного элемента формулы:

Стоимость * item/100

Для другого элемента:

Пункт * 5/100

Я хочу, чтобы пользователь мог генерировать формулу через web ui.

Затем, когда пользователь вводит переменные, я хочу вычислить результат.

Есть ли какие-либо пакеты или плагины для этого?

Спасибо.

4b9b3361

Ответ 1

Дарт Вейдер!

Здесь есть пара вариантов, и это зависит от ваших потребностей и нужно ли вам что-то очень сложное или что-то простое для понимания и расширения (возможно, в академических целях).

1) Начните с простого, легкого и настраиваемого. Я создал класс, который соответствует потребностям, указанным вами на вашем посту, однако он очень сырой и НЕ должен использоваться в коммерческих проектах без дальнейшего тестирования и модификации... Вы можете легко поднять его и увеличить на него, если вы хочу... Это показывает простой способ добиться того, что вам нужно. Код работает хорошо, но не учитывает математические приоритеты (например, круглые скобки или * над +). Его нужно адаптировать для этого... Код ниже, он прокомментирован и, мы надеемся, сам объясним:

public class DynamicFormula
{
    /// <summary>
    /// This simply stores a variable name and its value so when this key is found in a expression it gets the value accordingly.
    /// </summary>
    public Dictionary<string, double> Variables { get; private set; }

    /// <summary>
    /// The expression itself, each value and operation must be separated with SPACES. The expression does not support PARENTHESES at this point.
    /// </summary>
    public string Expression { get; set; }

    public DynamicFormula()
    {
        this.Variables = new Dictionary<string, double>();
    }

    public double CalculateResult()
    {
        if (string.IsNullOrWhiteSpace(this.Expression))
            throw new Exception("An expression must be defined in the Expression property.");

        double? result = null;
        string operation = string.Empty;

        //This will be necessary for priorities operations such as parentheses, etc... It is not being used at this point.
        List<double> aux = new List<double>();  

        foreach (var lexema in Expression.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries))
        {
            //If it is an operator
            if (lexema == "*" || lexema == "/" || lexema == "+" || lexema == "-")
            {
                operation = lexema;
            }
            else //It is a number or a variable
            {
                double value = double.MinValue;
                if (Variables.ContainsKey(lexema.ToLower())) //If it is a variable, let get the variable value
                    value = Variables[lexema.ToLower()];
                else //It is just a number, let just parse
                    value = double.Parse(lexema);

                if (!result.HasValue) //No value has been assigned yet
                {
                    result = value;
                }
                else
                {
                    switch (operation) //Let check the operation we should perform
                    {
                        case "*":
                            result = result.Value * value;
                            break;
                        case "/":
                            result = result.Value / value;
                            break;
                        case "+":
                            result = result.Value + value;
                            break;
                        case "-":
                            result = result.Value - value;
                            break;
                        default:
                            throw new Exception("The expression is not properly formatted.");
                    }
                }
            }
        }

        if (result.HasValue)
            return result.Value;
        else
            throw new Exception("The operation could not be completed, a result was not obtained.");
    }
    /// <summary>
    /// Add variables to the dynamic math formula. The variable should be properly declared.
    /// </summary>
    /// <param name="variableDeclaration">Should be declared as "VariableName=VALUE" without spaces</param>
    public void AddVariable(string variableDeclaration)
    {            
        if (!string.IsNullOrWhiteSpace(variableDeclaration))
        {
            var variable = variableDeclaration.ToLower().Split('=');    //Let make sure the variable name is LOWER case and then get its name/value
            string variableName = variable[0];
            double variableValue = 0;

            if (double.TryParse(variable[1], out variableValue))
                this.Variables.Add(variableName, variableValue);
            else
                throw new ArgumentException("Variable value is not a number");
        }
        else
        {
            //Could throw an exception... or just ignore as it not important...
        }
    }
}

Вот пример использования класса выше в приложении WPF (может использоваться в любом приложении С#)

    private void btCalculate_Click(object sender, RoutedEventArgs e)
    {
        string expression = tboxExpression.Text;    //"cost * item / 100" (IT MUST BE SEPARATED WITH SPACES!)
        string variable1 = tboxVariable1.Text;      //"item=10"
        string variable2 = tboxVariable2.Text;      //"cost=2.5"

        DynamicFormula math = new DynamicFormula();
        math.Expression = expression;   //Let define the expression
        math.AddVariable(variable1);    //Let add the first variable
        math.AddVariable(variable2);    //Let add the second variable

        try
        {
            double result = math.CalculateResult(); //In this scenario the result is 0,25... cost * item / 100 = (2.5 * 10 / 100) = 0,25
            //Console.WriteLine("Success: " + result);
            tboxResult.Text = result.ToString();
        }
        catch(Exception ex)
        {
            //Console.WriteLine(ex.Message);
            tboxResult.Text = ex.Message;
        }
    }

2) Если вам нужно что-то более надежное и для большинства реальных ситуаций, вы должны окончательно проверить FLEE: http://flee.codeplex.com/wikipage?title=Examples&referringTitle=Home

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

Надеюсь, что это поможет,

Луис Энрике Голл.

Ответ 2

Отметьте эту скрипту вы можете улучшить формулу, как хотите

HTML

<form id="ula">
  <h1>Insert your formula</h1>
  <input type="text" placeholder="Es: a(b+c)/2" />
  <input type="submit" value="Create form" />
</form>

CSS

body{font-family:arial,sans-serif;text-align:center}
input{padding:6px;border:1p solid #999;margin:10px auto}

JS

$('form').on('submit',function(e){
    e.preventDefault();
    $(this).hide();
    $('body').append($('<div />').hide().fadeIn(800));
    var labDiv=$('div:first');
    var varNames = [];
    var formula=$('input').val().toString();
    var varStr=formula.replace(/[^a-zA-Z]+/g, "");
    $.each(varStr.split(''), function(i, el) {
        if ($.inArray(el, varNames) === -1){
            varNames.push(el);
            labDiv.append('<input name="'+el+'" placeholder="'+el+' value.." /><br />');
        }
    });
    labDiv.prepend('<h1>'+formula+'</h1>');
    labDiv.append('<button id="newFormula">New formula</button><button id="calculate">Calculate</button>')
    $('#calculate').on('click',function(e){
        e.preventDefault();
        var result=formula.replace(/\(/g,'*(').replace(RegExp(':','g'),'/');
        for(var ct=0;ct<varNames.length;ct++){
            result=result.replace(new RegExp(varNames[ct], 'g'),$('input[name='+varNames[ct]+']').val());
            console.log(result)
        };
        labDiv.append('<h2>'+result.replace(/\*\(/g,'(')+'= <b>'+eval(result.replace(',','.'))+'</b></h2>');
    });
    $('#newFormula').one('click',function(e){
        e.preventDefault();
        labDiv.remove();
        $('form#ula input:first').val('');
        $('form#ula').fadeIn();
    });
})

Ответ 3

Поскольку вопрос был помечен jQuery, я предполагаю, что это веб-приложение. Если нет необходимости размещать формулу на сервере и оценивать ее там, используя ванильный JavaScript, вы должны сделать вашу жизнь намного проще. JavaScript - это динамический, нетипизированный и интерпретируемый язык, что означает, что вы можете динамически строить формулу в строке, а затем оценивать ее с помощью JavaScript-браузера.

Следующий пример кода из w3cscools.com:

var x = 10;
var y = 20;
var a = eval("x * y")

будет оцениваться до 200.

Если вам нужно оценить формулу на стороне сервера, проверьте, какие параметры у вас есть при запуске интерпретируемых языков на С#. В java есть Javascript runtime (Nashorn), поддерживаемый в JVM, поэтому можно легко оценить выражение JavaScript на стороне сервера.