[Regex] Rounding numbers
-
Hello,
I would like to round up decimals in a document, so that the numbers only have three decimal points. I know that this can be done with Regular Expressions… But i have no idea how these work.
Example:
16.0129754 --> 16.013Sincerely,
David -
I know @guy038 can do some magical stuff with regex, and with a simple example, like the one you showed, there would only have to be about 20 checks ((first digit 0-9) x (second digit 0-4 or second digit 5-9)). But to be able to handle all of these properly would require a monster.
16.01217 -> 16.012 16.01297 -> 16.013 16.01949 -> 16.019 16.01999 -> 16.020 16.14999 -> 16.150 16.19999 -> 16.200 16.99999 -> 17.000 19.99999 -> 20.000 199.9999 -> 200.000
Because for every digit that might possibly change, you have to have another layer. (And any digit from the thousandths digit and higher could potentially change)
What about rounding negative toward zero?
-0.0009 -> -0.001 -0.0004 -> -0.000 or 0.000
Also, what do you want done with numbers that have fewer than 3 digits after the decimal? Extend or keep as-is?
16.01 -> 16.010 # extend 16.01 -> 16.01 # keep as-is
What do you want to do if there’s a not-really-numeric, but looks like it, such as an IP address:
10.1.117.9
Most regex that you could come up with would probably stumble over that one.
Honestly, this is where a full-fledged programming language would shine. And since Python can have easy access to the contents of a text file opened in Notepad++ , using the Python Script plugin, that’s what I would recommend.
Here’s a simple example, though it doesn’t handle the IP-address exception.
# https://notepad-plus-plus.org/community/topic/15100/regex-rounding-numbers # version 1 #console.clear() #console.show() editor.documentEnd() end = editor.getCurrentPos() start = 0 #console.write("start:{}\n".format(start)) #console.write("end: {}\n".format(end)) #editor.documentStart() while start < end: position = editor.findText( FINDOPTION.REGEXP , start , end , "-*\d+\.\d{4,}") # find any that are at more than 3 digits after the decimal point # change to "-*\d+\.\d+" to handle any with at least one digit after the decimal (so 1.1 will go to 1.100, but 1. will be assumed to be the end of a sentence, and stay as 1.) # error handling if position is None: #console.writeError("editor.position is NONE => not found.\n") break # grab the matched text #console.write("editor: findText @ " + str(position[0]) + ":" + str(position[1]) + "\n") text = editor.getTextRange(position[0], position[1]) #console.write(text + "\n") # round it= rounded = round( float(text) , 3 ) text = "{:0.3f}".format(rounded) #console.write(text + "\n" ) # replace it with rounded editor.setSel(position[0], position[1]) editor.replaceSel(text) # next start = position[1] #console.writeError("DONE\n")
(the commented-out console.write commands, and similar, were from my debugging; useful if you want to see what’s going on as it’s searching)
If you place this in the
notepad++ directory\plugins\PythonScript\scripts\roundNumbers.py
, or in%AppData%\Config\PythonScript\scripts\roundNumbers.py
, you can run it usingPlugins > PythonScript > Scripts > roundNumbers
. -
@PeterJones
Wow that is awesome! I tried it out and it really works perfectly. That is exactly what i needed. Thank you very much!And the good thing is that i don’t have to round up IP addresses ;D.
Sincerely,
David -
Glad it works for you. (And I know you don’t have to round up IP addresses… but if you had a document that mixed your numbers and IP addresses, it might get confused… though since I’m looking for 4 digits after the decimal, it shouldn’t match valid IP. :-)
-
I haven’t really investigated it in the context of the current “rounding” problem, but off the top of my head it seems like the Pythonscript presented here was meant for doing this type of thing. Maybe. Maybe not. YMMV. :-D
-
Hello, @david-wanke, @perterjones and All,
David, I saw your post yesterday but I hadn’t time to reply, because I’ve just thought about some rounding cases, shown by Peter !
Of course, with a regex, no problem to change, for instance :
-
The floating number
12.45678
into the number12.457
-
And the floating number
12.45623
into the number12.456
using the rules :
-
If the fourth decimal digit, after the decimal point, is between
0
and4
, just truncate all decimal digits after the third one -
If the fourth decimal digit, after the decimal point, is between
5
and9
, increase by one the third digit and truncate all decimal digits after the third one
But, as regular expressions, mainly, do string operations, I would have, given the second rule, to take in account all values of the third decimal digit : if
3
then replace by4
, if7
then replace by8
and so on… ! And what about rounding12.99962
which should give13.000
!
So, it’s easy to understand that the rounding process is, fundamentally, a mathematical operation, which is usually handled by programming or script languages. For instance, in the Peter’s Python script, the line, below, does the mathematical operation ( I’m not a python expert but I don’t think I’m wrong about it !! )
while start < end: .... rounded = round( float(text) , 3 ) ....
As Peter said, this an example of the limitations of regular languages ;-))
Best Regards,
guy038
P.S. :
Refer to some Wiki documentation, below :
https://en.wikipedia.org/wiki/Regular_expression
https://en.wikipedia.org/wiki/Regular_language
Just note that I did not understand most of the second article, anyway ! But, it’s good, from time to time, to feel oneself, very intelligent… during some seconds ;-))
-
-