Как избавиться от ненужных круглых скобок в математическом выражении

StackOverflow https://stackoverflow.com/questions/1063316

  •  21-08-2019
  •  | 
  •  

Вопрос

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

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 select.Он не может превышать 255 символов, и я не могу изменить код, который создает эту формулу (в основном черный ящик ;)) Как вы видите, многие круглые скобки бесполезны.Не говоря уже о том факте, что:

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

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

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

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

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

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

Это было полезно?

Решение

Вы могли бы разобрать самые простые случаи:

([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 ...

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

Другие советы

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

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

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

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

T1 = (([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))
T2 = etc...

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

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

Я почти уверен, что для того, чтобы определить, какие круглые скобки не нужны, вы иметь чтобы оценить выражения внутри них.Поскольку вы можете вставлять круглые скобки, это своего рода рекурсивная проблема, которую регулярное выражение может решить только поверхностным образом и, скорее всего, приведет к неверным результатам.Если вы уже вычисляете выражение, возможно, вы хотели бы упростить формулу, если это возможно.Это также становится довольно сложным, и в некоторых подходах используются методы, которые также используются в машинном обучении, например, вы можете увидеть в следующей статье: http://portal.acm.org/citation.cfm?id=1005298

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top