2009-06-30 3 views
4

Salut Je me demandais s'il y avait une façon connue de se débarrasser des parenthèses inutiles dans la formule mathématique. La raison pour laquelle je pose cette question est que je dois minimiser une telle longueur de formuleComment se débarrasser des parenthèses inutiles dans l'expression mathématique

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]))); 

est essentiellement une partie de l'instruction select SQL. Il ne peut pas dépasser 255 caractères et je ne peux pas modifier le code qui produit cette formule (fondamentalement une boîte noire;)) Comme vous le voyez beaucoup de parenthèses sont inutiles. Sans parler du fait que:

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

donc je veux garder l'ordre des opérations Parenthèses, Multiplier/Diviser, Ajouter/Soustraire.

Im travaillant dans VB, mais la solution dans n'importe quelle langue ira bien.

Modifier

J'ai trouvé un problème inverse (ajouter entre parenthèses à une expression) Question. Je pensais vraiment que cela pourrait être accompli sans analyse lourde. Mais il semble que certains analyseurs qui vont passer par l'expression et la sauvegarder dans un arbre d'expression sont invisibles.

Répondre

2

Vous pouvez dépouiller les cas les plus simples:

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

DEVIENT

v.[6432] 

Vous ne devriez pas avoir le [ ] autour du nom de la table ou de son alias.

Vous pouvez raccourcir davantage si vous pouvez créer un alias pour les colonnes:

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

Ou même mettre toutes les tables interrogées en une seule sous-requête - vous donc pas besoin du préfixe de table:

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

il est évident que tout cela est un psedo code binaire, mais il devrait vous aider à simplifier la déclaration complète

+0

Merci Keith. Je testerai. – Pawel

0

Je suis assez sûr que, afin de déterminer quelles parenthèses sont inutiles, vous avez pour évaluer les expressions en leur sein. Parce que vous pouvez mettre des parenthèses entre parenthèses, c'est le genre de problème récursif qu'une expression régulière ne peut adresser que de façon superficielle, et très probablement à des résultats incorrects. Si vous évaluez déjà l'expression, vous voudrez peut-être simplifier la formule si possible. Cela devient également un peu délicat, et dans certaines approches utilise des techniques que l'on voit dans l'article suivant: http://portal.acm.org/citation.cfm?id=1005298

0

Si vos noms de variables ne changent pas significativement d'une requête à le suivant, vous pouvez essayer une série de commandes replace(). c'est-à-dire

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

Aussi, pourquoi ne peut-il dépasser 255 caractères? Si vous stockez ce champ en tant que champ de chaîne dans une table Access, vous pouvez essayer de placer la moitié de l'expression dans un champ et la seconde moitié dans un autre.

0

Vous pouvez également essayer d'analyser votre expression en utilisant ANTLR, yacc ou similaire et créer une arborescence d'analyse. Ces arbres optimisent généralement les parenthèses. Ensuite, il suffirait de créer une expression à partir de l'arbre (sans parenthèses évidemment).

Cela peut prendre plus de quelques heures pour que cela fonctionne. Mais l'analyse d'expression est généralement le premier exemple d'analyse générique, vous pouvez donc prendre un échantillon et le modifier selon vos besoins.

1

Si vous souhaitez supprimer les parenthèses inutiles dans votre expression, la solution générique consiste à analyser votre texte et à créer l'arborescence d'expression associée.

Puis, à partir de cet arbre, vous pouvez trouver le texte correspondant sans parenthèses non nécessaire, en appliquant certaines règles:

  • si le nœud est un « + », pas entre parenthèses sont nécessaires
  • si le nœud est un « * », puis entre parenthèses sont nécessaires pour les enfants de gauche (à droite) enfant que si la gauche (à droite) est un « + »
  • il de même pour «/»

Mais si votre le problème est juste de faire face à ces 255 caractères, vous pouvez probablement utiliser des variables intermédiaires pour stocker les résultats intermédiaires

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

Je sais que ce fil est vraiment vieux, mais comme il est consultable à partir Google. Je suis en train d'écrire un programme de calculatrice TI-83 plus qui aborde des problèmes similaires. Dans mon cas, j'essaie de résoudre réellement l'équation pour une variable spécifique en nombre, mais cela peut toujours être lié à votre problème, bien que j'utilise un tableau, donc il peut être plus facile pour moi de choisir des valeurs spécifiques.
Ce n'est pas tout à fait fait, mais il se débarrasse de la grande majorité des parenthèses avec (je pense), une solution plutôt élégante. Ce que je fais est de balayer à travers l'équation/fonction/quelquechose, en gardant une trace de chaque parenthèse ouvrante "(" jusqu'à ce que je trouve un parenthèse fermant "), à quel point je peux être assuré que je ne rencontrerai pas parenthèses plus profondément imbriquées. Y = ((3x + (2))) montrerait le (2) d'abord, puis le (3x + (2)), puis le ((3x + 2))).

Ce qu'il fait ensuite vérifie les valeurs immédiatement avant et après chaque parenthèse. Dans le cas ci-dessus, il retournera + et). Chacun d'entre eux est affecté d'une valeur numérique. Entre les deux, le plus élevé est utilisé. Si aucun opérateur n'est trouvé (*, /, +,^ou -), la valeur par défaut est 0.

Ensuite, je balaie l'intérieur des parenthèses. J'utilise un système de numérotation similaire, bien que dans ce cas j'utilise la valeur la plus basse trouvée, pas la plus élevée. Je par défaut à une valeur de 5 si rien n'est trouvé, comme ce serait le cas ci-dessus.L'idée est que vous pouvez attribuer un nombre à l'importance des parenthèses en soustrayant les deux valeurs. Si vous avez quelque chose comme un^sur l'extérieur des parenthèses (2 + 3)^5 ces parenthèses sont potentiellement très importantes, et recevraient une valeur élevée, (dans mon programme j'utilise 5 pour ^).

Il est possible cependant que les opérateurs internes rendent les parenthèses très peu importantes, (2)^5 où rien n'est trouvé. Dans ce cas, l'intérieur reçoit une valeur de 5. En soustrayant les deux valeurs, vous pouvez ensuite déterminer si un ensemble de parenthèses est nécessaire ou non en vérifiant si le nombre résultant est supérieur à 0. Dans le cas de (2 +3)^5, a^donnerait une valeur de 5, et a + donnerait une valeur de 1. Le nombre résultant serait 4, ce qui indiquerait que les parenthèses sont en fait nécessaires. Dans le cas de (2)^5 vous auriez une valeur interne de 5 et une valeur externe de 5, résultant dans une valeur finale de 0, montrant que les parenthèses sont sans importance, et peuvent être supprimés. L'inconvénient de ceci est que (au moins sur la TI-83) balayer l'équation tant de fois est ridiculement lent. Mais si la vitesse n'est pas un problème ... Je ne sais pas si cela aidera du tout, je pourrais être complètement hors sujet. J'espère que vous avez tout préparé et travaillé.