Как заставить таблицу данных распознавать функции - PullRequest
1 голос
/ 18 февраля 2012

Я где-то нашел в сети функцию, которая может выполнять строковые уравнения. Например, у меня может быть строка, такая как «1 + 5». Когда я передаю его в функцию, он возвращает, возвращает ответ. В моем приложении я извлекаю формулы из базы данных и заменяю неизвестные числа (такие как x, y или z) фактическими числами (1,2,3,4,5 и т. Д.), Введенными пользователем, когда они используют приложение. Однако для некоторых формул, которые мне нужно выполнить, нужны квадратные корни. Когда я пытаюсь передать строку, содержащую функцию Math.Sqrt (), она выдает ошибку, в которой говорится, что это неопределенная функция. Есть ли способ изменить функцию для распознавания этой функции?

Функция использует таблицу данных. Вот код:

public static double executeFormula(string expression)
{
    System.Data.DataTable table = new System.Data.DataTable();
    table.Columns.Add("expression", string.Empty.GetType(), expression);
    System.Data.DataRow row = table.NewRow();
    table.Rows.Add(row);
    return double.Parse((string)row["expression"]);
}  

Спасибо, ребята!

Ответы [ 4 ]

3 голосов
/ 18 февраля 2012

Используйте nCalc и покончите с этим.

Он поддерживает в точности то, о чем вы говорите, и расширяется для тех вещей, которые вы еще не достигли.

2 голосов
/ 18 февраля 2012

Боюсь, ответ - нет, как вы и написали. Функция, которую вы показываете, использует функцию DataColumn в таблицах данных, свойство Expression .

По сути, он поддерживает многие операторы, которые вы найдете в SQL:

Из документации:

OPERATORS

Concatenation is allowed using Boolean AND, OR, and NOT operators. You can use parentheses to group clauses and force precedence. The AND operator has precedence over other operators. For example:

(LastName = 'Smith' OR LastName = 'Jones') AND FirstName = 'John'

When creating comparison expressions, the following operators are allowed:

<

>

<=

>=

<>

=

IN

LIKE

The following arithmetic operators are also supported in expressions:

+ (addition)

- (subtraction)

* (multiplication)

/ (division)

% (modulus)

STRING OPERATORS

To concatenate a string, use the + character. Whether string comparisons are case-sensitive or not is determined by the value of the DataSet class's CaseSensitive property. However, you can override that value with the DataTable class's CaseSensitive property.

WILDCARD CHARACTERS

Both the * and % can be used interchangeably for wildcards in a LIKE comparison. If the string in a LIKE clause contains a * or %, those characters should be escaped in brackets ([]). If a bracket is in the clause, the bracket characters should be escaped in brackets (for example [[] or []]). A wildcard is allowed at the beginning and end of a pattern, or at the end of a pattern, or at the beginning of a pattern. For example:

"ItemName LIKE '*product*'"

"ItemName LIKE '*product'"

"ItemName LIKE 'product*'"

Wildcards are not allowed in the middle of a string. For example, 'te*xt' is not allowed.

PARENT/CHILD RELATION REFERENCING

A parent table may be referenced in an expression by prepending the column name with Parent. For example, the Parent.Price references the parent table's column named Price.

A column in a child table may be referenced in an expression by prepending the column name with Child. However, because child relationships may return multiple rows, you must include the reference to the child column in an aggregate function. For example, Sum(Child.Price) would return the sum of the column named Price in the child table.

If a table has more than one child, the syntax is: Child(RelationName). For example, if a table has two child tables named Customers and Orders, and the DataRelation object is named Customers2Orders, the reference would be:

Avg(Child(Customers2Orders).Quantity)

AGGREGATES

The following aggregate types are supported:

Sum (Sum)

Avg (Average)

Min (Minimum)

Max (Maximum)

Count (Count)

StDev (Statistical standard deviation)

Var (Statistical variance).

Aggregates are usually performed along relationships. Create an aggregate expression by using one of the functions listed above and a child table column as detailed in PARENT/CHILD RELATION REFERENCING above. For example:

Avg(Child.Price)

Avg(Child(Orders2Details).Price)

К сожалению, Square Root не является одной из функций, которые вы можете использовать. Однако, поскольку вы используете DataTable, вы можете просто циклически проходить по строкам и вычислять SquareRoot непосредственно из значения столбца. Представьте, что у вас есть столбец под названием «MyNumber». Затем вы можете сделать что-то вроде:

myDataTable.Columns.Add(new DataColumn() { Name = "MySquareRoot", DataType = typeof(Double)});

foreach(DataRow row in myDataTable.Rows)
{
  myDataTable["MySquareRoot"] = Math.Sqrt(Convert.ToDouble(myDataTable["MyNumber"]));
}

Вы можете поместить такую ​​функцию в метод Extension , если хотите.

В качестве альтернативы, вы можете использовать свои формулы где-то еще; вместо того, чтобы использовать DataTable для моделирования ваших данных, вы можете использовать класс. Сам класс может иметь свойства (или список или коллекцию), которые представляют ваши данные, и методы, которые воздействуют на ваши данные - тогда вы можете использовать любую функцию, какую захотите, в C #.

0 голосов
/ 18 февраля 2012

Взгляните на проект CodePlex бежать . Flee позволяет вам оценивать строковые выражения, такие как "sqrt(a^2 + b^2)" во время выполнения.

0 голосов
/ 18 февраля 2012

Вы можете создавать «Текстовые функции», которые люди смогут распознавать и использовать, и которые вы сможете анализировать в вашей программе.Взгляните на WolframAlpha или MS Math 4.0 .Например, вы можете сделать что-то вроде следующего:

if(str.IndexOf("sqrt")>-1)
{
    //replace sqrt for the actual Math.Sqrt() function
}

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...