0

I have a string like: "2E6 3.34e-5 3 4.6" and I want to use replaceAll to replace tokens like:

"((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)"

(i.e. two numbers with e or E between them) into the equivalent normal number format (i.e. replace "2E6" with "2000000" and "3.34e-5" with "0.0000334")

I wrote:

value.replaceAll("((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)", "($1)*10^($6)");

but I would like to actually multiply the 1st argument by 10 to the power of the 2nd argument, not just writing it that way .. Any ideas?

UPDATE

I did the following based on your suggesions:

Pattern p = Pattern.compile("((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)");
Matcher m = p.matcher("2E6 3.34e-5 3 4.6");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "WHAT HERE??"); // What HERE ??
}
m.appendTail(sb);
System.out.println(sb.toString());

UPDATE

Finally, this is what I reached:

// 32 #'s because this is the highest precision I need in my application
private static NumberFormat formatter = new DecimalFormat("#.################################");

private static String fix(String values) {
    String[] values_array = values.split(" ");
    StringBuilder result = new StringBuilder();
    for(String value:values_array){
        try{
            result.append(formatter.format(new Double(value))).append(" ");
        }catch(NumberFormatException e){ //If not a valid double, copy it as is
            result.append(value).append(" ");
        }
    }
    return result.toString().substring(0, result.toString().length()-1);
}
mtk
  • 13,221
  • 16
  • 72
  • 112
Hazem Elraffiee
  • 453
  • 7
  • 16
  • I think that a regex is not the best solution. Why do you need this done with regexes?? I think a workaround like the one here http://stackoverflow.com/questions/8666935/implemention-of-eval-in-java would be better. – Gabber Nov 27 '12 at 13:09
  • This is not what I want. If so, I'd easily split it using spaces, and for each string just do `new Double(my_string_value)`, but the problem is that the scientific notation (with e or E) is already accepted by Java, that's why wrapping into a Double Object doesn't help. – Hazem Elraffiee Nov 27 '12 at 13:17
  • Of course, I was just curious about why you need to do this with regexes :) – Gabber Nov 27 '12 at 13:19

4 Answers4

2
    StringBuffer buffer = new StringBuffer();

    Pattern regex = Pattern.compile("((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)");
    Matcher matcher = regex.matcher( "2E6 3.34e-5 3 4.6");
    while (matcher.find()) {

      String a = matcher.group(1); //The $1
      String b = matcher.group(6); //The $6
      String repl = null;
      if( a != null && b != null ) { //Check if both exist for this match
                      //Parse, do calculations and convert to string again
          repl = BigDecimal.valueOf( Double.parseDouble( a ) * Math.pow( 10, Double.parseDouble( b ) )).toString();
      }
      else {
          repl = matcher.group(0); //Else return unaffected
      }
      matcher.appendReplacement(buffer, repl);
    }
    matcher.appendTail(buffer);

    System.out.println( buffer.toString());
     //"2000000.0 0.0000334 3 4.6"
Esailija
  • 138,174
  • 23
  • 272
  • 326
1

If you need to convert scientific number notation into normal formal you can use DecimalFormat

public static void main(String[] args) {
    NumberFormat formatter = new DecimalFormat();

    double num1 = 2E6;
    formatter = new DecimalFormat("##########");
    System.out.println(formatter.format(num1)); 

    double num2 = 3.3e-5;
    formatter = new DecimalFormat("#.##########");
    System.out.println(formatter.format(num2));
}

Just add the logic to split the intial string over spaces and apply the above logic.

You can check more about the symbols like #(in this case) at the javadoc for DecimalFormat.

Symbol Location     Localized?  Meaning   
------------------------------------------------------------
#      Number       Yes         Digit, zero shows as absent 
mtk
  • 13,221
  • 16
  • 72
  • 112
0

I don't think you'll be able to do that with replaceAll method. You seem to know regex so I'll only point you in the right direction. Try the Pattern and Matcher class. With this, you can compile a regex pattern and find groups, and for example multiply the first group with 10 to the power of the group after e.

ddmps
  • 4,350
  • 1
  • 19
  • 34
0

If you want to do anything more complicated than copying groups verbatim from the match to the replacement then you'll have to do it longhand using the find() and appendReplacement/appendTail methods of Matcher. There's a good example in the javadoc for appendReplacement.

Inside the loop you can use m.group() to access the matched string, and m.group(n) to access the n'th parenthesis group, so you could create a suitable NumberFormat for the output format you need and then do something like

double val = Double.parseDouble(m.group());
m.appendReplacement(nf.format(val));

Or using String.format

m.appendReplacement(String.format("%f", val));

(or use BigDecimal if you can't be sure your values will all be representable as double).

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183