Im playing around with a genetic algorithm for solving eqvations.
So I've found this lib called NCAL which seems to be a nice way to go.
So I've tried to generate som random strings that will become NCALC Expressions like this:
private Expression getRandomExpression(int i)
{
string expression = ""; ;
double nr = random.NextDouble() * random.Next(100);
int sign = 1;
if (random.Next(2) > 0)
{
sign = -1;
}
Console.WriteLine("sign: " + sign + " i: " + i);
switch (i)
{
case 1:
expression = (sign.ToString() + "*" + nr.ToString() + "x");
break;
case 2:
expression = (sign.ToString() + nr.ToString() + "/x");
break;
case 3:
expression = (sign.ToString() + "x/" + nr.ToString());
break;
case 4:
expression = (sign.ToString() + "Pow(x," + nr.ToString()+")");
break;
default:
expression = (sign.ToString() + "*" + nr.ToString());
break;
}
return new Expression(expression);
}
And then I want to loop over these elements and check the sum against my goalfunction, like this:
public double calculateFitness(double[] goalFunction)
{
double fitness = 0.0;
for (int i = 1; i < goalFunction.Length; i++)
{
foreach (var element in genome)
{
try
{
element.Parameters["x"] = i;
var value = (double)element.Evaluate();
fitness += Math.Abs(goalFunction.ElementAt(i) - value);
}catch(Exception ex)
{
throw ex;
}
}
}
return fitness;
}
Seems easy but I keep getting this exception saying "line 1:1 missing EOF at 'x'". Any suggestions on how to solve this? Or easier ways to go. :)
I want to be able to find a equation representing the goalfunction.
br
Related
I have a string whose format like "945-20-4:397-3:320" or "945-20-41-90-4:397-3:320" . I need to split it bases upon 1st ":" and last "-" from left of 1st ":".
Like for "945-20-4:397-3:320" I need 2 part like '945-20' & '4:397-3:320'.
For "945-20-41-90-4:37-3:320-1:232", 2 part will be like '945-20-41-90' and '4:37-3:320-1:232'.
How to spilt it?
Here you go 3:D
void Main()
{
Splitter.Print(Splitter.GetParts("945-20-4:397-3:320"));
Splitter.Print(Splitter.GetParts("945-20-41-90-4:397-3:320"));
}
unsafe static class Splitter
{
public static ValueTuple<string, string> GetParts(string whole)
{
var builder = new StringBuilder();
fixed (char* parts = whole)
{
char* lastDashPosition = null;
var terminus = parts + whole.Length;
for (var x = parts; x < terminus; ++x)
{
switch (*x)
{
case ':':
builder.Remove((int)(lastDashPosition - parts),
(int)(x - lastDashPosition));
return ValueTuple.Create(builder.ToString(),
whole.Substring((int)(lastDashPosition + 1 - parts)));
case '-':
lastDashPosition = x;
break;
}
builder.Append(*x);
}
throw new InvalidOperationException("String not in expected format.");
}
}
public static void Print(ValueTuple<string, string> v)
{
Debug.Print("Token 1: " + v.Item1);
Debug.Print("Token 2: " + v.Item2);
}
}
I am currently working with a reverse polish notation calculator. It is fully functional but I am running into issues with text input that will then be used to calculate the values. The program breaks if introduce a formula like ( 8 5 + ) 6 * = . Is there a way to simply ignore any parentheses that show up in the input value? Also my program does split accordingly to space between each number but if I for get to add a space between operands or parentheses it also breaks: (8 5 +)6 * =. If it is an invalid formulas 12 + = ( missing a number) i would like to ignore them and just display in output textBox an error message.
Side Note: every formula is triggered by an ending =.
Code
namespace rpncalc
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string inputValue = "";
private void RPNCalc(string rpnValue)
{
Stack<int> stackCreated = new Stack<int>();
stackCreated.Clear();
string[] inputArray = rpnValue.Split();
int end = inputArray.Length - 1;
int numInput;
int i = 0;
do
{
if ("=+-*/%^".IndexOf(inputArray[i]) == -1)
{
try
{
numInput = Convert.ToInt32(inputArray[i]);
stackCreated.Push(numInput);
}
catch
{
MessageBox.Show("Please check the input");
}
}
else if (inputArray[i]== "+")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 + store1);
}
catch
{
}
}
else if (inputArray[i]== "-")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 - store1);
}
catch
{
}
}
else if (inputArray[i]== "%")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 % store1);
}
catch
{
}
}
else if (inputArray[i]== "*")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 * store1);
}
catch
{
}
}
else if (inputArray[i]== "/")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 / store1);
}
catch
{
}
}
else if (inputArray[i] == "^")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push((int)Math.Pow(store1, store2));
}
catch
{
}
}
}
while(i++ < end && inputArray[i]!= "=" && stackCreated.Count != 0);
string result = inputValue + " " + stackCreated.Pop().ToString() + Environment.NewLine;
TxtOutputBox.AppendText(result);
TxtInputBox.Clear();
}
private void TxtOutputBox_TextChanged(object sender, EventArgs e)
{
}
private void Btn_Calc_Click(object sender, EventArgs e)
{
inputValue = TxtInputBox.Text + " ";
RPNCalc(inputValue);
}
}
}
First of all, doing something like
rpnValue = rpnValue.Replace(" ", "").Replace("(","").Replace(")","");
as Sam's answer to this question recommends, would require a major rewrite of the entire algorithm. The problem is with the Replace(" ", "") part which eliminates spaces. However, the algorithm relies on Split to tokenise the input. If you eliminate spaces before that Split, instead of getting an array of numbers and operators, you will get a single string which cannot be processed by the existing code. Worse still both "12 3 * =" and "1 23 * =" will be converted to "123*=" !!!
To avoid making big changes change the code as follows:
Insert the following code before the Split:
rpnValue = rpnValue.Replace("("," ").Replace(")"," ");
This makes sure sure that parentheses are ignored as requested but in a way that makes (8 5 +)6 * = work.
And then make the following addition:
if (" \t\n\r".IndexOf(inputArray[i]) != -1) {
continue;
} else if ("=+-*/%^".IndexOf(inputArray[i]) == -1)
...
Also the code at the end of the loop needs to change:
while (i++ < end && inputArray[i] != "=");
if(stackCreated.Count != 1)
MessageBox.Show("Please check the input");
Hope that helps :-)
---------------------------The answer proper ends here ----------------------------------
Additional recommendation:
The question does not cover the issue of error reporting, but there was also something else I noticed: operations on the stack are surrounded by try catch statements and nothing happens in the catch part. This way an ill formatted input is not appropriately flagged. I would recommend deleting those try catch statements and putting a single one around the body of the function.
Some fun: My aim was to just answer the very specific question asked, but since seeing LB's beautiful piece of code was posted here, I updated the answer to include an alternative definition of RPNCalc that is just as consise but closer to your original approach which does not rely on regular expressions (except that expressions to be calculated do not end with an =).
private void RPNCalc(string rpnValue)
{
Stack<int> stackCreated = new Stack<int>();
try {
var tokens = rpnValue.Replace("(", " ").Replace(")", " ")
.Split().Where(s => !String.IsNullOrWhiteSpace(s));
foreach (var t in tokens) {
try {
stackCreated.Push(Convert.ToInt32(t));
} catch {
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
switch(t) {
case "+": store2 += store1; break;
case "-": store2 -= store1; break;
case "*": store2 *= store1; break;
case "/": store2 /= store1; break;
case "%": store2 %= store1; break;
case "^": store2 = (int) Math.Pow(store2, store1); break; /* was (int) Math.Pow(store1, store2); in the original code*/
default: throw new Exception();
}
stackCreated.Push(store2);
}
}
if(stackCreated.Count != 1)
MessageBox.Show("Please check the input");
else
textBox1.Text = stackCreated.Pop().ToString();
} catch {
MessageBox.Show("Please check the input");
}
}
how to remove unimportant characters from your string:
string str = inStr.Replace(" ", "").Replace("(","").Replace("etc.","");
Just a thought;
string input = #"( 8 5 + ) 6 *";
var tokens = Regex.Matches(input, #"(?<num>[0-9]+)|(?<op>[\+\-\*\/\^\%])").Cast<Match>()
.Select(m=> String.IsNullOrEmpty(m.Groups["num"].Value)
? new Tuple<string,string>("op",m.Groups["op"].Value)
: new Tuple<string,string>("num",m.Groups["num"].Value))
.ToList();
var fxns = new Dictionary<string, Func<int, int, int>>()
{
{"+",(i,j)=>j+i },
{"-",(i,j)=>j-i },
{"*",(i,j)=>j*i },
{"/",(i,j)=>j/i },
{"%",(i,j)=>j&i },
{"^",(i,j)=>(int)Math.Pow(j,i) },
};
Stack<int> stack = new Stack<int>();
foreach (var token in tokens)
{
if (token.Item1 == "num")
stack.Push(int.Parse(token.Item2));
else
stack.Push(fxns[token.Item2](stack.Pop(), stack.Pop()));
}
int finalResult = stack.Pop();
Is there any other method that is faster than doing like this?
private void EscapeStringSequence(ref string data)
{
data = data.Replace("\\", "\\\\"); // Backslash
data = data.Replace("\r", "\\r"); // Carriage return
data = data.Replace("\n", "\\n"); // New Line
data = data.Replace("\a", "\\a"); // Vertical tab
data = data.Replace("\b", "\\b"); // Backspace
data = data.Replace("\f", "\\f"); // Formfeed
data = data.Replace("\t", "\\t"); // Horizontal tab
data = data.Replace("\v", "\\v"); // Vertical tab
data = data.Replace("\"", "\\\""); // Double quotation mark
data = data.Replace("'", "\\'"); // Single quotation mark
}
-- Edited (Add explanation) --
Q1: Is there a reason why you need to speed it up? Is it causing a huge problem?
This part is used in this project: http://mysqlbackuprestore.codeplex.com/
I'm going to loop lots of various length of strings into this function repeatly. The whole process takes around 6-15 seconds to finished for millions of rows. There are other part get involve too. I'm trying to speed up every part.
Q2: How slow is it now?
OK, I'll capture the exact time used and post it here. I'll come back later. (will post the result tomorrow)
Update 29-06-2012
I have run test. This is the result:
Speed Test: String.Replace() - measured in miliseconds
Test 1: 26749.7531 ms
Test 2: 27063.438 ms
Test 3: 27753.8884 ms
Average: 27189.0265 ms
Speed: 100%
Speed Test: Foreach Char and Append - measured in miliseconds
Test 1: 8468.4547 ms
Test 2: 8348.8527 ms
Test 3: 8353.6476 ms
Average: 8390.3183 ms
Speed: 224% < faster
===================================
Update - Next Test (Another round)
===================================
------
Test Replace String Speed.
Test 1: 26535.6466
Test 2: 26379.6464
Test 3: 26379.6463
Average: 26431.6464333333
Speed: 100%
------
Test Foreach Char String Append.
Test 1: 8502.015
Test 2: 8517.6149
Test 3: 8595.6151
Average: 8538.415
Speed: 309.56%
------
Test Foreach Char String Append (Fix StringBuilder Length).
Test 1: 8314.8146
Test 2: 8330.4147
Test 3: 8346.0146
Average: 8330.41463333333
Speed: 317.29%
Conclusion:
Using Foreach Char Loop and Append is faster than String.Replace().
Thanks you very much guys.
--------
Below are the codes that I used to run the test: (edited)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.Write("Press any key to continue...");
Console.ReadKey();
Console.Write("\r\nProcess started.");
Test();
Console.WriteLine("Done.");
Console.Read();
}
public static Random random = new Random((int)DateTime.Now.Ticks);
public static string RandomString(int size)
{
StringBuilder sb = new StringBuilder();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
sb.Append(ch);
}
return sb.ToString();
}
public static void Test()
{
string text = "\\_\r\n\a\b\f\t\v\"'" + RandomString(2000) + "\\_\r\n\a\b\f\t\v\"'" + RandomString(2000);
List<TimeSpan> lstTimeUsed = new List<TimeSpan>();
int target = 100000;
for (int i = 0; i < 3; i++)
{
DateTime startTime = DateTime.Now;
for (int j = 0; j < target; j++)
{
if (j.ToString().EndsWith("000"))
{
Console.Clear();
Console.WriteLine("Test " + i.ToString());
Console.WriteLine(j.ToString() + " of " + target.ToString());
}
string data = text;
data = data.Replace("\\", "\\\\"); // Backslash
data = data.Replace("\r", "\\r"); // Carriage return
data = data.Replace("\n", "\\n"); // New Line
data = data.Replace("\a", "\\a"); // Vertical tab
data = data.Replace("\b", "\\b"); // Backspace
data = data.Replace("\f", "\\f"); // Formfeed
data = data.Replace("\t", "\\t"); // Horizontal tab
data = data.Replace("\v", "\\v"); // Vertical tab
data = data.Replace("\"", "\\\""); // Double quotation mark
data = data.Replace("'", "\\'"); // Single quotation mark
}
DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime;
lstTimeUsed.Add(ts);
}
double t1 = lstTimeUsed[0].TotalMilliseconds;
double t2 = lstTimeUsed[1].TotalMilliseconds;
double t3 = lstTimeUsed[2].TotalMilliseconds;
double tOri = (t1 + t2 + t3) / 3;
System.IO.TextWriter tw = new System.IO.StreamWriter("D:\\test.txt", true);
tw.WriteLine("------");
tw.WriteLine("Test Replace String Speed. Test Time: " + DateTime.Now.ToString());
tw.WriteLine("Test 1: " + t1.ToString());
tw.WriteLine("Test 2: " + t2.ToString());
tw.WriteLine("Test 3: " + t3.ToString());
tw.WriteLine("Average: " + tOri.ToString());
tw.WriteLine("Speed: 100%");
tw.Close();
lstTimeUsed = new List<TimeSpan>();
for (int i = 0; i < 3; i++)
{
DateTime startTime = DateTime.Now;
for (int j = 0; j < target; j++)
{
if (j.ToString().EndsWith("000"))
{
Console.Clear();
Console.WriteLine("Test " + i.ToString());
Console.WriteLine(j.ToString() + " of " + target.ToString());
}
string data = text;
var builder = new StringBuilder();
foreach (var ch in data)
{
switch (ch)
{
case '\\':
case '\r':
case '\n':
case '\a':
case '\b':
case '\f':
case '\t':
case '\v':
case '\"':
case '\'':
builder.Append('\\');
break;
default:
break;
}
builder.Append(ch);
}
}
DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime;
lstTimeUsed.Add(ts);
}
t1 = lstTimeUsed[0].TotalMilliseconds;
t2 = lstTimeUsed[1].TotalMilliseconds;
t3 = lstTimeUsed[2].TotalMilliseconds;
tw = new System.IO.StreamWriter("D:\\test.txt", true);
tw.WriteLine("------");
tw.WriteLine("Test Foreach Char String Append. Test Time: " + DateTime.Now.ToString());
tw.WriteLine("Test 1: " + t1.ToString());
tw.WriteLine("Test 2: " + t2.ToString());
tw.WriteLine("Test 3: " + t3.ToString());
tw.WriteLine("Average: " + ((t1 + t2 + t3) / 3).ToString());
tw.WriteLine("Speed: " + ((tOri) / ((t1 + t2 + t3) / 3) * 100).ToString("0.00") + "%");
tw.Close();
lstTimeUsed = new List<TimeSpan>();
for (int i = 0; i < 3; i++)
{
DateTime startTime = DateTime.Now;
for (int j = 0; j < target; j++)
{
if (j.ToString().EndsWith("000"))
{
Console.Clear();
Console.WriteLine("Test " + i.ToString());
Console.WriteLine(j.ToString() + " of " + target.ToString());
}
string data = text;
var builder = new StringBuilder(data.Length + 20);
foreach (var ch in data)
{
switch (ch)
{
case '\\':
case '\r':
case '\n':
case '\a':
case '\b':
case '\f':
case '\t':
case '\v':
case '\"':
case '\'':
builder.Append('\\');
break;
default:
break;
}
builder.Append(ch);
}
}
DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime;
lstTimeUsed.Add(ts);
}
t1 = lstTimeUsed[0].TotalMilliseconds;
t2 = lstTimeUsed[1].TotalMilliseconds;
t3 = lstTimeUsed[2].TotalMilliseconds;
tw = new System.IO.StreamWriter("D:\\test.txt", true);
tw.WriteLine("------");
tw.WriteLine("Test Foreach Char String Append (Fix StringBuilder Length). Test Time: " + DateTime.Now.ToString());
tw.WriteLine("Test 1: " + t1.ToString());
tw.WriteLine("Test 2: " + t2.ToString());
tw.WriteLine("Test 3: " + t3.ToString());
tw.WriteLine("Average: " + ((t1 + t2 + t3) / 3).ToString());
tw.WriteLine("Speed: " + ((tOri) / ((t1 + t2 + t3) / 3) * 100).ToString("0.00") + "%");
tw.Close();
}
}
}
var builder = new StringBuilder(data.Length + 20);
foreach (var ch in data)
{
switch (ch)
{
case '\\':
case '\r':
...
builder.Append('\\');
break;
}
builder.Append(ch);
}
return builder.ToString();
Try using a series of StringBuilder calls.
One hour ago, I spend a lot of time and finished the project but I had problems when saving it properly and totally lost it. However, I did it again but this time it don't work
I am not sure what I did wrong this time... I think I did exactly the same, but this time don't work?
I am getting the following error:
Error 1 An object reference is required for the non-static field,
method, or property
'ConsoleApplication1.Program.convertir(string)' C:\Documents and
Settings\modifiedForPersonalReasons\Program.cs 12 45 ConsoleApplication1
Here is my code, I was going to put just the error lines but then it would probably miss some information that we could need to spot the problem:
static void Main(string[] args)
{
Console.WriteLine("23.21 es " + convertir("23.21"));
Console.ReadLine();
}
public string convertir(string str)
{
string[] arr;
arr = str.Split('.');
string rtn = españolizar(arr[0], "peso");
if (arr.Length > 1)
{
rtn += " con " + españolizar(arr[1], "centavo");
}
return rtn;
}
public string españolizar(string str, string str2)
{
string[] list1 = { "cero", "un", "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve", "diez", "once", "doce", "trece", "catorce", "quince" };
string[] list2 = { "nivelarindexes", "dieci", "veinti", "trei", "cuare", "cincue", "sese", "sete", "oche", "nove" };
int numero = int.Parse(str);
string strNumero = Convert.ToString(numero);
int primerDigito = int.Parse(Convert.ToString(strNumero[0]));
int segundoDigito = 0;
if (strNumero.Length > 1)
{
segundoDigito = int.Parse(Convert.ToString(strNumero[1]));
}
int cases = -1;
if (numero > -1 && numero < 16)
{
cases = 0;
}
else if (numero > 15 && numero < 30)
{
cases = 1;
}
else if (numero > 29 && numero < 100)
{
cases = 2;
}
else if (numero == 100)
{
cases = 3;
}
string rtn = "";
switch (cases)
{
case 0:
rtn = list1[numero] + " " + str2;
if (primerDigito != 1)
{
rtn += "s";
}
break;
case 1:
if (numero != 20)
{
rtn = list2[primerDigito] + list1[segundoDigito];
}
else
{
rtn = "veinte";
}
rtn += " " + str2 + "s";
break;
case 2:
rtn = list2[primerDigito] + "nta";
if (segundoDigito != 0)
{
rtn += " y " + list1[segundoDigito];
}
rtn += " " + str2 + "s";
break;
case 3:
rtn = "cien " + str2 + "s";
break;
case -1:
rtn = "número invalido";
break;
}
rtn = rtn.Replace("iun", "iún").Replace("idos", "idós").Replace("itres", "itrés").Replace("iseis", "iséis");
return rtn;
}
I could swear I didn't change anything :C
Change public string convertir(string str) to public static string convertir(string str). Do the same for the españolizar function.
You are getting this message because you are calling non-static methods from a static method. You need an instance of this class to call the non-static methods, or make the other methods static.
You must change your two methods to static methods as you can't call a static method from a non-static method.
See here for an explanation as to why.
To fix this, you must change the following:
public string convertir(string str)
To
public static string convertir(string str)
And change
public string españolizar(string str, string str2)
To
public static string españolizar(string str, string str2)
The convertir method needs to be static (same as Main).
I want to store combination of method invocations and formulas as text or script into database. for example, i want to store something like this in Database as a string and execute it somewhere in code:
if(Vessel.Weight>200)
{
return Cargo.Weight*Cargo.Tariff*2
}
else
{
Cargo.Weight*Cargo.Tariff
}
invocation:
var cost = executeFormula("CalculateTariff",new {Cargo= GetCargo(), Vessel=GetVessel()});
because these rules will change frequently and i don't want to deploy dll (CLR solution), and i don't want to store these rules as SP and mix business rules with DAL.
Any idea or tool?
If you place all values in a hashtable or a dictionary by changing the . with a _ (Vessel.Weight will become "Vessel_Weight") and simplify the syntax to one line it will be much easier to create a solution. This rule can be written for example as:
result=(Vessel_Weight>200)
?(Cargo_Weight*Cargo_Tariff*2)
:(Cargo_Weight*Cargo_Tariff)
Having rules defined like the above one you can use the following (draft, not optimal ...) code as a guide for a properly coded function that will do the job. I repeat that the following code is not perfect, but bottom line it's more than enough as a proof of concept.
Dictionary<string, dynamic> compute = new Dictionary<string, dynamic>();
compute.Add("Vessel_Weight", 123);
compute.Add("Cargo_Weight", 24);
compute.Add("Cargo_Tariff", 9);
string rule = "result=(Vessel_Weight>200)
?(Cargo_Weight*Cargo_Tariff*2)
:(Cargo_Weight*Cargo_Tariff)";
string process = rule.Replace(" ", "");
foreach (Match level1 in Regex.Matches(process, "\\([^\\)]+\\)"))
{
string parenthesis = level1.Value;
string keepit = parenthesis;
Console.Write("{0} -> ", parenthesis);
// replace all named variable with values from the dictionary
foreach (Match level2 in Regex.Matches(parenthesis, "[a-zA-z0-9_]+"))
{
string variable = level2.Value;
if (Regex.IsMatch(variable, "[a-zA-z_]+"))
{
if (!compute.ContainsKey(variable))
throw new Exception("Variable not found");
parenthesis = parenthesis.Replace(variable, compute[variable].ToString());
}
}
parenthesis = parenthesis.Replace("(", "").Replace(")", "");
Console.Write("{0} -> ", parenthesis);
// do the math
List<double> d = new List<double>();
foreach (Match level3 in Regex.Matches(parenthesis, "[0-9]+(\\.[0-9]+)?"))
{
d.Add(double.Parse(level3.Value));
parenthesis = Regex.Replace(parenthesis, level3.Value, "");
}
double start = d[0];
for (var i = 1; i < d.Count; i++)
{
switch (parenthesis[i - 1])
{
case '+':
start += d[i];
break;
case '-':
start -= d[i];
break;
case '*':
start *= d[i];
break;
case '/':
start /= d[i];
break;
case '=':
start = (start == d[i]) ? 0 : 1;
break;
case '>':
start = (start > d[i]) ? 0 : 1;
break;
case '<':
start = (start < d[i]) ? 0 : 1;
break;
}
}
parenthesis = start.ToString();
Console.WriteLine(parenthesis);
rule = rule.Replace(keepit, parenthesis);
}
Console.WriteLine(rule);
// peek a value in case of a condition
string condition = "[0-9]+(\\.[0-9]+)?\\?[0-9]+(\\.[0-9]+)?:[0-9]+(\\.[0-9]+)?";
if (Regex.IsMatch(rule, condition))
{
MatchCollection m = Regex.Matches(rule, "[0-9]+(\\.[0-9]+)?");
int check = int.Parse(m[0].Value) + 1;
rule = rule.Replace(Regex.Match(rule, condition).Value, m[check].Value);
}
Console.WriteLine(rule);
// final touch
int equal = rule.IndexOf("=");
compute.Add(rule.Substring(0, equal - 1), double.Parse(rule.Substring(equal + 1)));
Now the result is a named item in the dictionary. This way you may process more rules in the sense of intermediate results and have a final rule based on them. The code as is written does not guarantee correct execution order for arithmetic operations, but if you keep your rules simple (and possibly split them if is needed) your will achieve your goal.