【问题标题】:Creating dynamic formula创建动态公式
【发布时间】:2015-12-07 16:23:05
【问题描述】:

我需要创建一个用户界面,用户将建立一个公式。即:

对于一项公式是:

成本 * 物品 / 100

对于另一个项目:

物品* 5 / 100

我希望用户能够通过 web ui 生成公式。

然后当用户输入我想要计算结果的变量时。

是否有任何软件包或插件可以做到这一点?

谢谢。

【问题讨论】:

  • 那么我如何在我的应用中拥有电子表格?
  • 您是否在寻找以 UI 为中心的库或计算引擎,或两者兼而有之?
  • 两者。它们既可以是客户端也可以是服务器端。
  • 你似乎想要的是解释器模式 -> 你应该阅读它link 包或插件的事情是大多数时候乳清会允许用户执行很多操作
  • 请记住,您的用户仍然会责怪您和您的程序,即使他们的计算是错误的。

标签: c# jquery


【解决方案1】:

达斯维达!

这里有几个选项,这取决于您的需求以及您是需要一些非常复杂的东西还是需要一些简单易懂和扩展的东西(可能是出于学术目的)。

1) 让我们从简单、容易和可定制的开始。我创建了一个满足您在帖子中指定的需求的类,但是它非常原始,不应该在没有进一步测试和修改的情况下用于商业项目......如果你可以轻松地拿起它并增加它想要...它显示了一种简单的方法来实现您所需要的。该代码运行良好,但没有考虑数学优先级(例如括号或 * over +)。为了做到这一点,它需要进行调整...... 代码如下,它被注释并希望自我解释:

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's get the variable value
                    value = Variables[lexema.ToLower()];
                else //It is just a number, let's just parse
                    value = double.Parse(lexema);

                if (!result.HasValue) //No value has been assigned yet
                {
                    result = value;
                }
                else
                {
                    switch (operation) //Let's 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's make sure the variable's 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 应用程序中使用上述类的示例(可用于任何 C# 应用程序)

    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's define the expression
        math.AddVariable(variable1);    //Let's add the first variable
        math.AddVariable(variable2);    //Let's 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】:

    检查this fiddle您可以根据需要改进公式

    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();
        });
    })
    

    【讨论】:

    • 此代码导致计算不正确,例如,如果我使用 a(b^2+c) 我得到 2(5^2+4) = 6,如果我使用 a(b*b+ c) 我得到 2(5*5+4)=58,所以也许你没有包括权力?
    【解决方案3】:

    由于问题是用 jQuery 标记的,我假设这是一个 Web 应用程序。除非需要将公式发布到服务器并在那里使用 vanilla JavaScript 对其进行评估,否则您的生活会变得如此轻松。 JavaScript 是一种动态、无类型和解释性语言,这意味着您可以在字符串中动态构建公式,然后由浏览器的 javascript 引擎对其进行评估。

    以下来自 w3cscools.com 的代码示例:

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

    将评估为 200。

    但是,如果您需要在服务器端评估公式,请检查在 C# 上运行解释语言时有哪些选项。在 Java 中,JVM 中有一个 Javascript 运行时 (Nashorn),因此可以轻松地在服务器端评估 JavaScript 表达式。

    【讨论】:

      猜你喜欢
      • 2015-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 2022-12-24
      • 2023-02-09
      相关资源
      最近更新 更多