• Login
Community
  • Login

[Regex] Rounding numbers

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
6 Posts 4 Posters 8.0k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D
    David Wanke
    last edited by Jan 16, 2018, 11:30 AM

    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.013

    Sincerely,
    David

    1 Reply Last reply Reply Quote 0
    • P
      PeterJones
      last edited by PeterJones Jan 16, 2018, 3:13 PM Jan 16, 2018, 3:12 PM

      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 using Plugins > PythonScript > Scripts > roundNumbers.

      D 1 Reply Last reply Jan 16, 2018, 4:57 PM Reply Quote 4
      • D
        David Wanke @PeterJones
        last edited by David Wanke Jan 16, 2018, 4:57 PM Jan 16, 2018, 4:57 PM

        @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

        1 Reply Last reply Reply Quote 1
        • P
          PeterJones
          last edited by Jan 16, 2018, 9:10 PM

          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. :-)

          1 Reply Last reply Reply Quote 0
          • S
            Scott Sumner
            last edited by Jan 17, 2018, 12:55 PM

            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

            1 Reply Last reply Reply Quote 1
            • G
              guy038
              last edited by guy038 Jan 17, 2018, 9:58 PM Jan 17, 2018, 9:57 PM

              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 number 12.457

              • And the floating number 12.45623 into the number 12.456

              using the rules :

              • If the fourth decimal digit, after the decimal point, is between 0 and 4, just truncate all decimal digits after the third one

              • If the fourth decimal digit, after the decimal point, is between 5 and 9, 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 by 4, if 7 then replace by 8 and so on… ! And what about rounding 12.99962 which should give 13.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 ;-))

              1 Reply Last reply Reply Quote 1
              • T Terry R referenced this topic on Nov 20, 2021, 6:32 PM
              4 out of 6
              • First post
                4/6
                Last post
              The Community of users of the Notepad++ text editor.
              Powered by NodeBB | Contributors