I have relational expressions stored in a database, that i have as strings in an iOS app. I would like to evaluate the conditions within the strings in C#, similar to the logic in the following psudo code:
string str1= "x > 0";
string str2= "y < 1";
int x = 1;
int y=0;
if(str1 && str2)
{
//do stuff
}
If the expressions are simple like the one in the example, then you can simply parse them. But if you have more complex expressions in mind, then I recommend taking a look at C# Expression Trees. The documentation does a good job of explaining it.
A much easier method would be to use library like: https://github.com/davideicardi/DynamicExpresso
Use Afk Expression Library (Afk link)
and try following code it will solve your problem as I sorted out.
Required NameSpace
using Afk.Expression;
Your code for sending expression as string to library evaluator
string str1 = "x > 0";
string str2 = "y < 1";
int x = 10;
int y = 0;
var st1=str1.Replace("x",x.ToString());
var st2 = str2.Replace("y", y.ToString());
if (Eval(st2) && Eval(st1))
{
//checked
}
Eval Method evaluate mathematical and conditional expression
bool Eval(string st)
{
ExpressionEval eval = new ExpressionEval(st);
return Convert.ToBoolean(eval.Evaluate().ToString());
}
As well read for more other libraries that you can utilize for your as such problems.
Related
This question already has answers here:
Is there a string math evaluator in .NET?
(18 answers)
Closed 3 years ago.
Is there an easy way to parse a simple math expression represented as a string such as (x+(2*x)/(1-x)), provide a value for x, and get a result?
I looked at the VSAEngine per several online examples, however, I am getting a warning that this assembly has been deprecated and not to use it.
If it makes any differences, I am using .NET 4.0.
I urge caution against choosing an existing generic expression evaluator over a purpose-built math evaluator. The reason for this is expression evaluators are not limited to math. A clever individual could use this to create an instance of any type in the framework and call any method on the type, and that would allow him to do some decidedly unwelcome things. For example: new System.Net.WebClient().DownloadFile("illegalchildpornurl", "C:\openme.gif") will evaluate just fine in most of those, and do just what it sounds like it would (and make you a felon at the same time).
This doesn't mean don't look for something that's already written; it just means be careful. You want one that does math, and only math. Most of what's already out there isn't that picky.
I was recently using mXparser, which is a math parser library. It gives you a lot of flexibility, such as variables, functions, constants, operators. You will find below a few usage examples:
Example 1 - simple formula
Expression e = new Expression("1 + pi");
double v = e.calculate();
Example 2 - formula with variables, functions, etc.
Argument x = new Argument("x = 2");
Constant a = new Constant("a = sin(10)");
Function f = new Function("f(t) = t^2");
Expression e = new Expression("2*x + a - f(10)", x, a, f);
double v = e.calculate();
https://mxparser.codeplex.com/
https://mathparser.org/
Found recntly - you can try the syntax (and see the use case) via the Scalar Calculator app that is powered by mXparser.
Best regards
You can try using DataTable.Compute.
A related one is DataColumn.Expression.
Also check out: Doing math in vb.net like Eval in javascript
Note: I haven't used these myself.
I would also have a look at Jace (https://github.com/pieterderycke/Jace). Jace is a high performance math parser and calculation engine that supports all the .NET flavors (.NET 4.x, Windows Phone, Windows Store, ...). Jace is also available through NuGet: https://www.nuget.org/packages/Jace
Here is one way to do it. This code is written in Java. Note it does not handle negative numbers right now, but you can add that.
public class ExpressionParser {
public double eval(String exp, Map<String, Double> vars){
int bracketCounter = 0;
int operatorIndex = -1;
for(int i=0; i<exp.length(); i++){
char c = exp.charAt(i);
if(c == '(') bracketCounter++;
else if(c == ')') bracketCounter--;
else if((c == '+' || c == '-') && bracketCounter == 0){
operatorIndex = i;
break;
}
else if((c == '*' || c == '/') && bracketCounter == 0 && operatorIndex < 0){
operatorIndex = i;
}
}
if(operatorIndex < 0){
exp = exp.trim();
if(exp.charAt(0) == '(' && exp.charAt(exp.length()-1) == ')')
return eval(exp.substring(1, exp.length()-1), vars);
else if(vars.containsKey(exp))
return vars.get(exp);
else
return Double.parseDouble(exp);
}
else{
switch(exp.charAt(operatorIndex)){
case '+':
return eval(exp.substring(0, operatorIndex), vars) + eval(exp.substring(operatorIndex+1), vars);
case '-':
return eval(exp.substring(0, operatorIndex), vars) - eval(exp.substring(operatorIndex+1), vars);
case '*':
return eval(exp.substring(0, operatorIndex), vars) * eval(exp.substring(operatorIndex+1), vars);
case '/':
return eval(exp.substring(0, operatorIndex), vars) / eval(exp.substring(operatorIndex+1), vars);
}
}
return 0;
}
}
You need to import java.util.Map.
Here is how I use this code:
ExpressionParser p = new ExpressionParser();
Map vars = new HashMap<String, Double>();
vars.put("x", 2.50);
System.out.println(p.eval(" 5 + 6 * x - 1", vars));
Another option you may want to look into is the Spring.NET Framework's expression evaluation functionality. It can do a lot more than math, too.
However, the entire Spring.NET Framework might be a bit of overkill for your needs if you don't require the rest of the functionality.
Related: Equation expression parser with precedence.
As I answered in this thread (Best Free C# Math Parser using variables, user defined functions, custom operators), you can use Mathos Parser, which you can simply paste into your source code.
Mathos.Parser.MathParser parser = new Mathos.Parser.MathParser();
string expr = "(x+(2*x)/(1-x))"; // the expression
decimal result = 0; // the storage of the result
parser.LocalVariables.Add("x", 41); // 41 is the value of x
result = parser.Parse(expr); // parsing
Console.WriteLine(result); // 38.95
I recomend you to use MEEL for this.
// parse string to IExpression (symbolic type)
IExpression expression = BaseExpression.Parse("(x+(2*x)/(1-x))");
// create your own collection for attributes
var attributes = new MathAttributeCollection();
// create local variable named "x" with value 5
var attributeX = new ScalarAttrInt("x") {Value = new ScalarConstInt(5)};
attributes.Add(attributeX);
// execute math expression where x=5
var result = expression.Execute(attributes);
MessageBox.Show(result.GetText());
// result: 2.5
In Ruby, I can put multiple statements in a interpolated string, eg.
puts "#{a = 1; b = 2; a + b;}"
Or I can put them in multiple lines like this:
puts "#{a = 1;
b = 2;
a + b;}"
Can I do the same thing in C# 6? I've tried but failed. Below is my C# code.
Console.WriteLine($#"haha
{int a = 1;
int b = 2;
a+b;}
heihei");
When I try to run the C# program, I got:
CS1525 Invalid expression term 'int'
CS1073 Unexpected token 'a'
I hope someone can help.
You can't have full code blocks in your string interpolation statements. You can only do evaluations inside.
So this works (pulled the variables outside):
int a = 1;
int b = 2;
Console.WriteLine($#"haha
{a+b}
heihei");
And this too (do evaluation only):
Console.WriteLine($#"haha
{1+2}
heihei");
Ruby is different then C# in your case you write full code in your string interpolation so it's not working.
Console.WriteLine($"Name = {name}, hours = {hours:hh}")
or
Console.WriteLine($#"haha {1+2} heihei");
For Ref: Microsoft C#
Is there a way a comparison in a string value can return a Boolean value. Example.
If (5 > 5000) would obviously return a false value. But what i wanted to do is have the "5 > 5000" return a false value.
Example.
string com = "5 > 10";
so is there a way to make this com variable return a false value as if it was a comparison between integers.
No built-in way but NCalc can help here
NCalc.Expression expr = new NCalc.Expression("5>10");
bool b = (bool)expr.Evaluate();
You can even use parameters
NCalc.Expression expr = new NCalc.Expression("a<b");
expr.EvaluateParameter += (name, args) =>
{
if (name == "a") args.Result = 5;
if (name == "b") args.Result = 10;
};
bool b = (bool)expr.Evaluate();
There is no built-in way to do this.
Although there are a couple of ways to approach this, one is to simply parse the text yourself. I did this in the code presented in the article A C# Expression Evaluator. You might want to review that code.
No, this can't be done directly.
You should write your own class or extend the String class. For handling a string such as "5 < 10", you need your own method.
You should search the string for signs that indicate comparison, such as "<", "==" etc, then split it and perform the comparison.
Basically: doing it yourself is the only way, but you can try to do it in an elegant way.
Short answer: no.
Long answer: feel free to parse the string yourself, looking for > < and =. Split by whitespace, parse ints then evaluate. It might get harder if you want it to work with parentheses as well...
Not directly, per se (short of the unsafe Javascript eval-execute-my-data hack) but you can try parsing it yourself, depending on how complicated of an expression you want to accept. For example, this should work with the string you have:
var arr = com.Split('>').Select(x=>int.Parse(x.Trim())).ToArray();
return arr[0] > arr[1];
You can also use regular expressions to get more complicated (untested, but it ought to work):
var r = new Regex(#"(\d+)\b*(<|>|=|<=|>=)\b*(\d+)")
var match = r.Match(com);
if(match.Success)
{
var a = int.Parse(match.Captures[0]);
var b = int.Parse(match.Captures[2]);
switch(match.Captures[1])
{
case "<":
return a < b;
case "=":
return a = b;
case ">":
return a > b;
case "<=":
return a <= b;
case "<=":
return a >= b;
}
}
//uh-oh
throw new ArgumentException("com");
Consider using FLEE:
Flee is an expression parser and evaluator for the .NET framework. It allows you to compute the value of string expressions such as sqrt(a^2 + b^2) at runtime. It uses a custom compiler, strongly-typed expression language, and lightweight codegen to compile expressions directly to IL. This means that expression evaluation is extremely fast and efficient. Try out the demo, which lets you generate images based on expressions, and see for yourself.
With FLEE you can easily accomplish this using something like:
var con = new ExpressionContext();
const string com = #"5 > 5000";
var comparison = con.CompileDynamic(com);
var result = comparison.Evaluate();
MessageBox.Show(result.ToString());
HTH...
We have semi-complicated expressions in the format:
"25 + [Variable1] > [Variable2]"
We need an expression evaluator to parse the expression and use a callback to ask for the variable values and work out the overall result of the expression. It has to be a callback as there are thousands of variables.
We need the usual math operators but also things like "if" etc. The richer the language the better.
We can use any language we want. Anyone have any suggestions?
Have you considered using Mono.CSharp.Evaluator? It seems like this in conjunction with an appropriatelly set InteractiveBaseClass would do the trick quite nicely, and with minimal effort.
Note that the following uses Mono 2.11.1 alpha.
using System;
using System.Diagnostics;
using Mono.CSharp;
using NUnit.Framework;
public class MonoExpressionEvaluator
{
[Test]
public void ProofOfConcept()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof (Variables);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var result = evaluator.Evaluate("25 + Variable1 > Variable2");
Assert.AreEqual(25 + Variables.Variable1 > Variables.Variable2, result);
Console.WriteLine(result);
}
public class Variables
{
internal static Func<double> Variable1Callback;
public static Double Variable1 { get { return Variable1Callback(); } }
internal static Func<double> Variable2Callback;
public static Double Variable2 { get { return Variable2Callback(); } }
}
}
Real shame it runs a little slow. For instance, on my i7-m620 it takes almost 8 seconds to run this 10,000 times:
[Test]
public void BenchmarkEvaluate()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof(Variables);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var sw = Stopwatch.StartNew();
for (int i = 1; i < 10000; i++)
evaluator.Evaluate("25 + Variable1 > Variable2");
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
00:00:07.6035024
It'd be great if we could parse and compile it to IL so we could execute it at .NET speeds, but that sounds like a bit of a pipe dream...
[Test]
public void BenchmarkCompiledMethod()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof(Variables);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var method = evaluator.Compile("25 + Variable1 > Variable2");
object result = null;
method(ref result);
Assert.AreEqual(25 + Variables.Variable1 > Variables.Variable2, result);
Variables.Variable2Callback = () => 31;
method(ref result);
Assert.AreEqual(25 + Variables.Variable1 > Variables.Variable2, result);
var sw = Stopwatch.StartNew();
for (int i = 1; i < 10000; i++)
method(ref result);
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
00:00:00.0003799
Oh my.
Need excel-like expression constructs like IF? Build your own!
[Test]
public void ProofOfConcept2()
{
Evaluator evaluator = new Evaluator(new CompilerContext(new CompilerSettings(), new ConsoleReportPrinter()));
evaluator.InteractiveBaseClass = typeof(Variables2);
Variables.Variable1Callback = () => 5.1;
Variables.Variable2Callback = () => 30;
var result = evaluator.Evaluate(#"IF(25 + Variable1 > Variable2, ""TRUE"", ""FALSE"")");
Assert.AreEqual("TRUE", result);
Console.WriteLine(result);
}
public class Variables2 : Variables
{
public static T IF<T>(bool expr, T trueValue, T falseValue)
{
return expr ? trueValue : falseValue;
}
}
Check out NCalc. It's .NET and should support your requirements.
Pure expression evaluators are actually pretty easy to write.
See this SO answer which shows expression evaluators in a dozen langauges. You should be able to adapt one of these:
Code Golf: Mathematical expression evaluator (that respects PEMDAS)
EDIT: Whoever dinged this obviously didn't go and examine the solutions there. Yes, there are a bunch that are crammed tight to meet the golf-rules (typically "smallest") but most of them are explained pretty clearly with a cleartext version of algorithm.
Well ... you need a language. You have C#, VB.Net, IronPython, IronRuby, and others.
Simple replace the open variables using regex (maybe you even know them ahead and just need a string.Replace) and then compile the script using CodeDOM (for C# or VB.Net) or use the DLR (IronPython, IronRuby). You can simply add the variables as method parameters in the method wrapper you use to encapsulate your code (for CodeDOM) or just inject the variables in the DLR.
Both variants we implemented in our team in business with less effort and reliable effort.
When you urgently regquire the callback, well the add to the solutions above a method which communicate with the host of the programming language with a name like ValueOf(string). So you can write
ValueOf("A") > ValueOf("B") - 10
Have fun.
http://code.google.com/p/bc-expression/
Handles variable lookup via a lambda or block callback.
Understands numeric, string and boolean constants.
Unary operators + - !
Operators || && < <= == != >= > + - * / %
Grouping with ( )
Raises an Expression::SyntaxError if there's a syntax error.
What's the cleanest/best way in C# to convert something like 400AMP or 6M to an integer? I won't always know what the suffix is, and I just want whatever it is to go away and leave me with the number.
You could use a regular expression:
Regex reg = new Regex("[0-9]*");
int result = Convert.ToInt32(reg.Match(input));
Okay, here's a long-winded solution which should be reasonably fast. It's similar to Guffa's middle answer, but I've put the conditions inside the body of the loop as I think that's simpler (and allows us to fetch the character just once). It's a matter of personal taste really.
It deliberately doesn't limit the number of digits that it matches, because if the string is an integer which overflows Int32, I think I'd rather see an exception than just a large integer :)
Note that this also handles negative numbers, which I don't think any of the other solutions so far do...
using System;
class Test
{
static void Main()
{
Console.WriteLine(ParseLeadingInt32("-1234AMP"));
Console.WriteLine(ParseLeadingInt32("+1234AMP"));
Console.WriteLine(ParseLeadingInt32("1234AMP"));
Console.WriteLine(ParseLeadingInt32("-1234"));
Console.WriteLine(ParseLeadingInt32("+1234"));
Console.WriteLine(ParseLeadingInt32("1234"));
}
static int ParseLeadingInt32(string text)
{
// Declared before loop because we need the
// final value
int i;
for (i=0; i < text.Length; i++)
{
char c = text[i];
if (i==0 && (c=='-' || c=='+'))
{
continue;
}
if (char.IsDigit(c))
{
continue;
}
break;
}
return int.Parse(text.Substring(0, i));
}
}
It's possibly not the cleanest method, but it's reasonably simple (a one liner) and I would imagine faster than a regex (uncompiled, for sure).
var str = "400AMP";
var num = Convert.ToInt32(str.Substring(0, str.ToCharArray().TakeWhile(
c => char.IsDigit(c)).Count()));
Or as an extension method:
public static int GetInteger(this string value)
{
return Convert.ToInt32(str.Substring(0, str.ToCharArray().TakeWhile(
c => char.IsDigit(c)).Count()));
}
Equivalently, you could construct the numeric string from the result of the TakeWhile function, as such:
public static int GetInteger(this string value)
{
return new string(str.ToCharArray().TakeWhile(
c => char.IsNumber(c)).ToArray());
}
Haven't benchmarked them, so I wouldn't know which is quicker (though I'd very much suspect the first). If you wanted to get better performance, you would just convert the LINQ (extension method calls on enumerables) to a for loop.
Hope that helps.
There are several options...
Like using a regular expression:
int result = int.Parse(Regex.Match(input, #"^\d+").Groups[0].Value);
Among the fastest; simply looping to find digits:
int i = 0;
while (i < input.Length && Char.IsDigit(input, i)) i++;
int result = int.Parse(input.Substring(0, i));
Use LastIndexOfAny to find the last digit:
int i = input.LastIndexOfAny("0123456789".ToCharArray()) + 1;
int result = int.Parse(input.Substring(0, i));
(Note: breaks with strings that has digits after the suffix, like "123asdf123".)
Probably fastest; parse it yourself:
int i = 0;
int result = 0;
while (i < input.Length) {
char c = input[i];
if (!Char.IsDigit(c)) break;
result *= 10;
result += c - '0';
i++;
}
If all you want to do is remove an unknown postfix from what would otherwise be an int, here is how I would do it:
I like a utility static method I call IsInt(string possibleInt) which will, as the name implies, return True if the string will parse into an int. You could write this same static method into your utility class (if it's not there already) and try:
`string foo = "12345SomePostFix";
while (!Tools.ToolBox.IsInt(foo))
{
foo = foo.Remove(foo.Length - 1);
}
int fooInt = int.Parse(foo);`