12

Is it possible to use a regular expression to perform rounding on a number? The problem is that I've got a lot of numbers to more than 2 decimal places in a file and I need to move them to 2 decimal places.

It's in source file so ideally I'd like to use Visual Studio's find and replace, but I'm not against the idea of writing a script to run on the file (treating it as plain text) if regex doesn't have the answer.

Matthew Steeples
  • 7,858
  • 4
  • 34
  • 49

4 Answers4

11

You can't do it with regexes alone, as Ryan pointed out, but you can use regexes to find decimals in your input and use a callback function on the replace operation.

In Python:

>>> import re
>>> text = "1.234 and 99.999; .555 12.345"
>>> simpledec = re.compile(r"\d*\.\d+")
>>> def mround(match):
...     return "{:.2f}".format(float(match.group()))
...
>>> re.sub(simpledec, mround, text)
'1.23 and 100.00; 0.56 12.35'

The regex to match decimals is very simplistic; it doesn't match exponential notation, for example, but it should give you an idea.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • Thanks for that. It was what I expected to be doing – Matthew Steeples Sep 30 '11 at 09:15
  • Replace in a json: cutstr='{"probability": {"neg": 0.33828654512348322, "neutral": 0.79405570286895666,.... ReplaceRegExpr('\d\d{4,12}[},]',cutstr,' ',false)) {"probability": {"neg": 0.3382 "neutral": 0.7940 ... – Max Kleiner Jan 12 '21 at 22:28
7

I don't think you can round the numbers, since regular expressions can't do addition.

You could truncate them as follows (this will work in Notepad++):

find (\d*\.\d\d)\d*

replace with \1

Ryan Gross
  • 6,423
  • 2
  • 32
  • 44
4

Well... at least you can search for (\d+\.\d\d\d)\d* and replace it with round($1, 2).

Yeah, perhaps this is not what you expected :)

Karolis
  • 9,396
  • 29
  • 38
  • That's a great suggestion and would solve my problem but I've gone with Tim's answer as I'd like to keep the code clean – Matthew Steeples Sep 30 '11 at 09:14
  • 2
    Neat. With JavaScript: `string.replace(/(\d+\.\d\d\d)\d*/,function($0,$1) {return Math.round($1*100)/100;})` – Christophe Feb 27 '15 at 20:41
  • @Christophe : with JS we can also use `return Number($1).toFixed(3).toString()` (ofcourse the speed debate ensues) – gawkface Sep 04 '17 at 04:20
  • Beter late than never: In javascript - you need to apply the global flag for mutiple replacements: `string.replace(/(\d+\.\d\d\d)\d*/g, (s) => { return Math.round( parseFloat(s) * 100 ) / 100).toString(); });` –  Aug 09 '18 at 11:17
  • The above comment throws an error. Corrected version: `string.replace(/(\d+\.\d\d\d)\d*/g, (s) => { return Math.round( parseFloat(s) * 100 ) / 100}).toString();` https://jsfiddle.net/uso58hkL/ – Zach Saucier Jan 15 '20 at 18:34
0

I just came up with a simple way to do this for rounding results in a set of Google BigQuery results -- their subset of SQL doesn't let you round to a specific decimal place a.f.a.i.k., but it does support regexes.

Since, as someone mentioned above, regexes can't add, then as long you can add a constant to each value somehow, you can still get the rest of the way there:

+ 0.5 if you're rounding up to the nearest integer
+ 0.05 if you are rounding up to the nearest 0.1
+ 0.005 if you are rounding up to the nearest 0.01 etc.

... etc. - basically add half of your smallest precision value to get the rounding effect.

And then run a regex extract on the result. The above ones will probably work done for this.

Here's the regex pattern I settled on -- which is not the most robust, but will work on a number that is already known to be in basic float format:

+ for 0.1 precision use (-?\d*\.?\d?)
+ for 0.01 precision use (-?\d*\.?\d?\d?)
+ for 0.001 precision use (-?\d*\.?\d?\d?\d?)

Then it's both rounded and truncated.

Reagan R
  • 1
  • 1