我有一个桌面 c# 应用程序,它使用公式根据用户的输入计算值。
如果有一种方法可以从文本文件中获取公式并使用它而不是对其进行硬编码,那么我正在徘徊,这将使程序编译后更改公式变得容易。
问题是将此字符串从文本文件转换为可在代码中使用的公式。
谢谢
我有一个桌面 c# 应用程序,它使用公式根据用户的输入计算值。
如果有一种方法可以从文本文件中获取公式并使用它而不是对其进行硬编码,那么我正在徘徊,这将使程序编译后更改公式变得容易。
问题是将此字符串从文本文件转换为可在代码中使用的公式。
谢谢
我想您可能想尝试直接解析公式字符串来计算结果。然而使用XML
来存储你的公式也是一个好主意(虽然你必须自己输入从实际公式转换而来的公式,但要做到这一点,你必须了解一些用于表达公式的 XML 结构。不要'不用担心,很简单)。首先我谈谈表达公式的 XML 结构。它有两种类型的节点:
操作数节点:该节点有名称operand
,有 1 个被调用的属性value
,并且没有任何子元素。它value
可以是数字或变量(占位符),以便您可以在运行时传递一些值。例子:
<operand value="1234"/>
<operand value="x"/>
Operator 节点:此节点与它支持的 operator 具有相似的名称。为简单起见,我假设您的公式仅支持 4 种运算符:+
, -
, *
, ./
加法用 tag 表示<add>
,减法用 tag 表示<sub>
,乘法用 tag 表示<mul>
,除法用 tag 表示<div>
。每个算子节点有 2 个元素(因为算子是二元的)。每个元素都是一个操作数。这对上面提到的节点并不严格operand
,可以是另一个operator
节点。这就是关于 XML 结构的全部知识。例子:
//expression of (x + y)
<add>
<operand value="x"/>
<operand value="y"/>
</add>
以下 XML 是公式的示例f(x,y) = (x + y - x/y) * (x-y) / 5
。此公式需要在运行时计算 2 个变量。
<mul>
<sub>
<add>
<operand value="x"/>
<operand value="y"/>
</add>
<div>
<operand value="x"/>
<operand value="y"/>
</div>
</sub>
<div>
<sub>
<operand value="x"/>
<operand value="y"/>
</sub>
<operand value="5"/>
</div>
</mul>
这是处理它的代码:
public class ArgumentInfo
{
public string Name { get; set; }
public double Value { get; set; }
}
public double ComputeNode(XElement node, params ArgumentInfo[] args)
{
var operands = node.Elements().ToList();
if (operands.Count == 0)
{
if (node.Name != "operand") throw new ArgumentException("XML formula error! Please check it");
ArgumentInfo o = args.FirstOrDefault(x => x.Name == node.Attribute("value").Value);
return o == null ? double.Parse(node.Attribute("value").Value) : o.Value;
}
if (operands.Count != 2) throw new ArgumentException("XML formula error! Please check it");
var a = ComputeNode(operands[0], args);
var b = ComputeNode(operands[1], args);
if (node.Name == "add") return a + b;
else if (node.Name == "sub") return a - b;
else if (node.Name == "mul") return a * b;
else return a / b;
}
public double Compute(string xmlFormula, params ArgumentInfo[] args)
{
XDocument doc = XDocument.Parse(xmlFormula);
return ComputeNode(doc.Root, args);
}
public double ComputeFormulaFromPath(string xmlFormulaPath, params ArgumentInfo[] args)
{
XDocument doc = XDocument.Load(xmlFormulaPath);
return ComputeNode(doc.Root, args);
}
//Example f(x,y) = (x + y - x/y) * (x-y) / 5 with (x,y) = (10,20)
var result = ComputeFormulaFromPath(@"E:\yourFormula.xml", new ArgumentInfo {Name = "x", Value = 10},
new ArgumentInfo {Name="y",Value=20});
//The result is -59
您还可以定义一些调用<formula>
来表达公式的标签,并且您可以在同一个xml
文件中定义许多公式。
是的,这是个好主意。但是,如果您从文本文件中获取数据类型,则会出现问题。您还需要对此进行良好的验证。
根据我的建议,您必须为此使用 XML。
它易于处理,您可以选择更准确的数据作为比较文本文件
根据您的方法,我认为您不能动态使用公式。我并不是说这是不可能的,但让它成为可能需要在你的应用程序中添加更多的额外内容。
举一个更简单的案例
您的文本文件有几个简单的公式,格式如下:
Add : a+b
Simple Interest : (P*R*T)/100
Progression = 1+2+3... n+ (n+1)+(n+2)....
P,R,T,n,a,b
那么你能告诉我你将如何选择上面示例中的公式的动态部分。
AFAIK,如果您将公式放在代码中,这将很容易。是的,您可以做一件常见的事情。创建一个类文件,该文件将包含程序所需的所有公式作为方法的通用方法,并在需要时调用它们。
见下文
public static class MathematicalBench
{
public static double SimpleInterest(double principal, double rate, double time)
{
return (principal*rate*time)/100;
}
}
现在在需要的地方打电话
Class A:
private void SomeMethod1()
{
// Your logic
var interest= MathematicalBench.SimpleInterest(128765.98,3.6,16);
}
Another Class B:
private void SomeNewMethod1()
{
// Your logic
var interest= MathematicalBench.SimpleInterest(6523898,6.2,10);
}
当然,这将更加灵活和容易。