Using replace in a character in the middle of a String to add text before and after the String

Asked

Viewed 247 times

4

I have this expression stored in a String:

1 * Math.pow(x, 3.0) + 4 * Math.pow(x, 2.0) + 1 * Math.pow(x, 1.0) + 27

However, I use a derivation library that only accepts the character ^ to make potentiation, then I make a conversion in this String, being like this:

1*x^3.0+4*x^2.0+1*x^1.0+27

The derivation function returns me a String derived in the same String converted (1.0+3.0*x^2.0+8.0*x), and I need to calculate the derived expression with the function eval(), who only accepts the Math.pow() as a potentiation function. I tried to use:

str = str.replaceAll("[x\\^]", "Math.pow\\(\\x\\,");
str = str.replaceAll("[(?:\\,(?=0-9))]", "1");

And the first line already helps a lot, but I don’t know very well how I would add the exponent with parenthesis after the comma or how to know the exponent.

EDIT: I created the following code:

static String reConvertString(String str) {
    Pattern patterne = Pattern.compile("[^\\^]*\\^");
    Matcher matchere = patterne.matcher(str);
    int count = 0;
    while (matchere.find()) {
        count++;//conta a quantidade de ocorrencias do caractere ^
    }

    for(int i=0;i<count;i++) {
        int index = str.indexOf("^");
        str = str.replaceFirst("\\^", "z");//substituo por um caractere qualquer depois que acho a primeira ocorrencia
        System.out.println(index);
        str = str.replaceFirst("[xz]", "Math.pow\\(\\x\\, ");//o x^2.0 agora fica xz com o replace

        String teste=str.substring(index+1, index+2);//pega a potência
        str = str.replace(" ", teste+")");//fecha o parêntese da função
    }
    return str;
}

But my output was like this:

10.0*Math.Pow(Math.Pow(x,4),t)Z4.0-15.0*xz2.0

I don’t know where the t.

1 answer

5


The t came from the word Math and the problem is in the indexes that you pass to substring (the values end up coinciding with the t).

Anyway, to solve this with regex, I’m assuming some premises:

  • the basis always is x (but in the end I put an alternative to bases that are not x)
  • the exponent is always a number (and not a more complex expression, so the solution below does not consider cases as x ^ (a + b / c), for example)

For this simpler case, we can use something like:

String str = "1*x^3.0+4*x^2.0+1*x^1.0+27";
str = str.replaceAll("x\\^(\\d+(?:\\.\\d+)?)", "Math.pow(x, $1)");
System.out.println(str);

I’m assuming that the basis is always x, then I put the character itself x in the expression.

Then I use \\^: the ^ has special meaning in regex (meaning "the beginning of the string"), then for him to "lose his powers" I need to escape him with \ - but within a String this character needs to be written as \\, then the final result is \\^. Thus, it corresponds to the character itself ^.

Then, for the exponent, I use (\\d+(?:\\.\\d+)?). Explaining from the inside out:

The outermost parentheses form a catch group, so I can refer it later, using $1.

Internal parentheses use syntax (?:, that forms a catch group (so they don’t create a special variable, like the $1). And the ? that comes after makes this group optional.

That is, the exponent may be both 1 how much 1.0. And this value is captured in group 1 (because it is the first pair of parentheses), and can be referenced later with $1 - which is the value I use in the substitution expression.

That is, regex checks whether there is a x followed by ^, followed by number and exchange for Math(x, $1), whereas $1 is the value of the number, which was captured by the capture group.

The result is:

1*Math.Pow(x, 3.0)+4*Math.Pow(x, 2.0)+1*Math.Pow(x, 1.0)+27


The above regex assumes that there are no spaces between the x, the ^ and the exponent. If you want to consider spaces, you can use \\s* (zero or more spaces):

str = str.replaceAll("x\\s*\\^\\s*(\\d+(?:\\.\\d+)?)", "Math.pow(x, $1)");

If the basis can be anything other than x, can change to \w+ (one or more alphanumeric characters), or [a-z]+ (one or more letters of a to z):

String str = "1*x^3.0+4*y^2.0+1*z^1.0+27";
str = str.replaceAll("([a-z]+)\\s*\\^\\s*(\\d+(?:\\.\\d+)?)", "Math.pow($1, $2)");
System.out.println(str);

Now I put the letters inside a capture group, so the expression has two groups: one for the base and the other for the exponent. In the substitution expression, they are respectively $1 and $2. The result is:

1*Math.Pow(x, 3.0)+4*Math.Pow(y, 2.0)+1*Math.Pow(z, 1.0)+27

If the variable can be uppercase or lowercase, just switch to [a-zA-Z]+.


This works for simpler expressions. But if you have more complex things (like (x * 1 - 2) ^ (a - (1.24 / y))), then it becomes too complex to use regex, because then you would have to analyze many factors, such as whether the parentheses are balanced (something that is much easier to do without regex). In this case, I suggest searching for lexical analyzers or parsers specific.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.