Manipulation de chaîne du type Substitution de chaîne en expression mathématique

Imaginez quelque chose comme

exp(49/200)+(x-49/200) 

Je veux passer comme argument de la fonction "roundn" quelle que soit l'opération qui n'est pas une addition ou une soustraction. Donc, mon expression est devenue

 roundn(exp(roundn(49/200,n)),n)+(x - roundn(49/200,n) 

Bien, l'expression que je veux manipuler est la suivante:

 exp(49/200)+exp(49/200)*(x-49/200)+1/2*exp(49/200)*(x-49/200)^2+1/6*exp(49/200)*(x- 49/200)^3+1/24*exp(49/200)*(x-49/200)^4+1/120*exp(49/200)*(x-49/200)^5+1/720*exp(49/200)*(x-49/200)^6+1/5040*exp(49/200)*(x-49/200)^7+1/40320*exp(49/200)*(x-49/200)^8+1/362880*exp(49/200)*(x-49/200)^9+1/3628800*exp(49/200)*(x-49/200)^10+1/39916800*exp(49/200)*(x-49/200)^11 

Je suis à la recherche d'une méthode (qui inclut tout programme) non basée sur la programmation de la langue, autant de lots ou quelque chose comme ça …

Essaye ça:

 ro='roundn(' # roundn open rc=',n)' # roundn close fun='exp\(' expression='exp(49/200)+(x-49/200)' echo "$expression" | perl -pe "s/$fun[^)]*\K\)/)$rc/g; s/(?<!\^)[0-9\/*]+[0-9]/$ro\$&$rc/g; s/$fun[^)]*/$ro\$&/g" 

Qui devrait vous donner:

 roundn(exp(roundn(49/200,n)),n)+(x-roundn(49/200,n)) 

Votre expression plus longue devrait aboutir à:

Roundn (exp (roundn (49/200, n)), n) + roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) + roundn (1/2, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 2 + roundn (1/6, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 3 + roundn (1/24, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 4 + roundn (1/120, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 5 + roundn (1/720, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 6 + roundn (1/5040, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 7 + roundn (1/40320, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 8 + roundn (1/362880, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 9 + roundn (1/3628800, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n)) ^ 10 + roundn (1/39916800, n) * roundn (exp (roundn (49/200, n)), n) *
(X-roundn (49/200, n) ^ 11

Explication

  • /exp\([^)]*\K\)/)$rc/g – fermer exp (), ajouter roundn close
    • Pour les chaînes qui commencent par "exp (" et se terminent par ")"
    • \K fait le "exp (" une largeur de largeur nulle de sorte que seul le paren de fermeture est remplacé
  • s/(?<!\^)[0-9\/*]+[0-9]/$ro\$&$rc/g – chaînes de chiffres avec mult et div, surround avec roundn open et roundn close
    • Les chaînes de chiffres qui ne commencent pas avec "^" mais peuvent contenir "/" ou "*"
    • Doit être deux ou plus de caractères totaux – il y a probablement une meilleure façon de le faire
    • Carat est négatif look-behind (largeur nulle) donc il n'est pas inclus lorsque le remplacement est effectué
  • s/exp\([^)]*/$ro\$&/g – ouvrir exp (), ajouter roundn open
    • Avant "exp (" suivi de zéro ou plus de caractères qui ne sont pas ")", ajouter roundn open
  • $ro , $rc et $fun sont des variables shell
    • L'enveloppement du script Perl entre guillemets permet d'étendre ces variables
  • $& contient la totalité de la correspondance, à l'exception des parties à largeur nulle
    • Échapper n'est probablement pas nécessaire, mais je l'ai fait au cas où – pour éviter de confondre la coquille

Il ne serait pas trop difficile de le faire fonctionner s'il y a plus d'une fonction. Cependant, il sera probablement complètement décomposé s'ils sont imbriqués.

Modifier:

Voici une version de script Perl:

 $ro = "roundn("; $rc = ",n)"; $fun = "exp\\("; while (<>) { s/$fun[^)]*\K\)/)$rc/g; s/(?<!\^)[0-9\/*]+[0-9]/$ro$&$rc/g; s/$fun[^)]*/$ro$&/g; print } 

Exécutez-le comme ceci:

 perl script.pl < data.txt 

Eh bien, j'essaie d'exécuter votre code … Je crée un petit programme (practicalcase1.pl) avec le premier paragraphe de code que vous avez écrit:

 ro='roundn(' # roundn open rc=',n)' # roundn close fun='exp\(' expression='exp(49/200)+(x-49/200)' echo "$expression" | perl -pe "s/$fun[^)]*\K\)/)$rc/g; s/(?<!\^)[0-9\/*]+[0-9]/$ro\$&$rc/g; s/$fun[^)]*/$ro\$&/g" 

Mais je reçois quelques messages sur le cmd des fenêtres:

 Semicolon seems to be missing at practicalcase1.pl line 1 Semicolon seems to be missing at practicalcase1.pl line 2 Semicolon seems to be missing at practicalcase1.pl line 3 Semicolon seems to be missing at practicalcase1.pl line 4 String found where operator expected at practicalcase1.pl line 5, near "echo "$expression"" (Do you need to predeclare echo?) String found where operator expected at practicalcase1.pl line 6, near "pe "s/$fun[^)]*\K\)/)$rc/g; s/(?<!\^)[0-9\/*]+[0-9]/$ro\$&$rc/g"" (Do you need to predeclare pe?) Can´t modify constant item in scalar assigment at practicalcase1.pl line 2, near "rc" syntax error at practicalcase1.pl line 2, near "rc" Execution of practicalcase1.pl aborted due to compilation errors. 

Que puis-je faire avec les erreurs de type "point-virgule semble …"? Ce que j'ai supposé, je dois faire avec l'erreur "Chaîne trouvée par l'opérateur …"? Qu'en est-il de «Impossible de modifier l'élément constant en scalaire …»? Qu'en est-il de "erreur de syntaxe sur practicalcase1.pl line2 …"

Merci beaucoup!