Как избавиться от лишних скобок в математическом выражении - PullRequest
4 голосов
/ 30 июня 2009

Привет, мне было интересно, есть ли какой-нибудь известный способ избавиться от лишних скобок в математической формуле. Причина, по которой я задаю этот вопрос, заключается в том, что я должен минимизировать такую ​​длину формулы

if((-if(([V].[6432])=0;0;(([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])
+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))=0;([V].[6428])*
((((([V].[6443]))/1000*([V].[6445])*([V].[6448])+(([V].[6443]))*([V].[6445])*
([V].[6449])+([V].[6445])*([V].[6450])))*(1-([V].[6446])));

это в основном часть оператора выбора sql. Он не может превышать 255 символов, и я не могу изменить код, который создает эту формулу (в основном черный ящик;)) Как видите, многие круглые скобки бесполезны. Не говоря уже о том, что:

((a) * (b)) + (c) = a * b + c

Поэтому я хочу сохранить порядок операций Скобки, Умножение / Деление, Сложение / Вычитание.

Я работаю в VB, но решение на любом языке будет в порядке.

Редактировать

Я обнаружил противоположную проблему (добавьте скобки в выражение) Вопрос .

Я действительно думал, что это можно сделать без тяжелого разбора. Но кажется, что некоторый синтаксический анализатор, который пройдет через выражение и сохранит его в дереве выражений, неизбежен.

Ответы [ 6 ]

2 голосов
/ 30 июня 2009

Вы можете лишить простейших случаев:

([V].[6432]) and (([V].[6443]))

Становится

v.[6432]

Вам не нужно указывать [] вокруг имени таблицы или ее псевдонима.

Вы можете сократить его, если можете использовать псевдонимы столбцов:

select v.[6432] as a, v.[6443] as b, ....

Или даже поместить все запрашиваемые таблицы в один подзапрос - тогда вам не понадобится префикс таблицы:

if((-if(a=0;0;(a-b)*((c/1000*d
+c*e+f)*(1-g))))=0;h*
(((c/1000*b*d+c*b*
e+b*f))*(1-g));

select [V].[6432] as a, [V].[6445] as b, [V].[6443] as c, [V].[6448] as d, 
    [V].[6449] as e, [V].[6450] as f,[V].[6446] as g, [V].[6428] as h ...

Очевидно, что это немного псевдокод, но это должно помочь вам упростить полный оператор

1 голос
/ 04 апреля 2011

Я знаю, что эта тема действительно старая, но ее можно искать в Google.

Я пишу калькулятор TI-83 plus, который решает подобные проблемы. В моем случае я пытаюсь на самом деле решить уравнение для конкретной переменной по числу, но оно все равно может относиться к вашей проблеме, хотя я использую массив, поэтому мне будет проще выбрать конкретные значения. ..
Это не совсем сделано, но оно избавляет от подавляющего большинства скобок с (я думаю), несколько элегантным решением.

Что я делаю, так это просматриваю уравнение / функцию / что угодно, отслеживая каждую открывающую скобку "(" пока не найду закрывающую скобку ")", и в этот момент я могу быть уверен, что не столкнусь с какой-либо более глубоко вложенные скобки.

y = ((3x + (2))) сначала покажет (2), затем (3x + (2)), а затем ((3x + 2))).

Затем он проверяет значения непосредственно перед и после каждой круглой скобки. В случае выше, это возвратило бы + и). Каждому из них присваивается числовое значение. Между двумя из них используется высшее. Если операторы не найдены (*, /, +, ^ или -), я по умолчанию принимаю значение 0.

Затем я просматриваю скобки. Я использую аналогичную систему нумерации, хотя в этом случае я использую самое низкое найденное значение, а не самое высокое. Я по умолчанию на значение 5, если ничего не найдено, как было бы в случае выше.

Идея состоит в том, что вы можете присвоить число важности скобок, вычтя два значения. Если у вас есть что-то вроде ^ вне скобок (2 + 3) ^ 5 эти скобки потенциально очень важны, и им будет дано большое значение (в моей программе я использую 5 для ^).

Возможно, однако, что внутренние операторы сделают скобки очень неважными, (2) ^ 5 где ничего не найдено В этом случае внутреннему элементу будет присвоено значение 5. Вычитая эти два значения, вы можете определить, является ли необходимым набор скобок, просто проверив, больше ли полученное число больше 0. В случае (2 +3) ^ 5, a ^ даст значение 5, а + даст значение 1. Результирующее число будет 4, что будет означать, что скобки действительно нужны. В случае (2) ^ 5 у вас будет внутреннее значение 5 и внешнее значение 5, в результате в конечном значении 0, показывая, что круглые скобки не важны и могут быть удалены.

Недостатком этого является то, что (по крайней мере, на TI-83) сканирование по уравнению очень много раз смехотворно медленное. Но если скорость не проблема ... Не знаю, поможет ли это вообще, я могу быть совершенно не в теме. Надеюсь, у вас все работает и работает.

1 голос
/ 30 июня 2009

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

Затем из этого дерева вы можете найти соответствующий текст без лишних скобок, применив некоторые правила:

  • если узел - "+", скобки не требуются
  • если узел является "*", тогда круглые скобки требуются для левого (правого) дочернего элемента, только если левый (правый) дочерний элемент является "+"
  • То же самое относится к "/"

Но если ваша проблема состоит только в том, чтобы справиться с этими 255 символами, вы, вероятно, можете просто использовать промежуточные переменные для хранения промежуточных результатов

T1 = (([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))
T2 = etc...
0 голосов
/ 30 июня 2009

Вы также можете попробовать проанализировать выражение, используя ANTLR, yacc или подобное, и создать дерево разбора. Эти деревья обычно оптимизируют скобки. Тогда вам просто нужно создать выражение обратно из дерева (без скобок, очевидно).

Хотя это может занять несколько часов. Но синтаксический анализ выражений обычно является первым примером общего анализа, поэтому вы можете взять образец и изменить его по своему усмотрению.

0 голосов
/ 30 июня 2009

Если имена ваших переменных существенно не меняются от одного запроса к следующему, вы можете попробовать серию команд replace (). т.е.

X=replace([QryString],"(([V].[6443]))","[V].[6443]")

Кроме того, почему он не может превзойти 255 символов? Если вы храните это как строковое поле в таблице Access, вы можете попробовать поместить половину выражения в 1 поле, а вторую - в другое.

0 голосов
/ 30 июня 2009

Я почти уверен, что для того, чтобы определить, какие скобки не нужны, у вас есть для оценки выражений внутри них. Поскольку вы можете вкладывать круглые скобки, это - своего рода рекурсивная проблема, которую регулярное выражение может решить только поверхностным образом и, скорее всего, к неверным результатам. Если вы уже оцениваете выражение, возможно, вы хотели бы упростить формулу, если это возможно. Это также становится немного сложным, и в некоторых подходах используются методы, которые также встречаются в машинном обучении, такие как вы можете увидеть в следующей статье:

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