Loading ...
Sorry, an error occurred while loading the content.

Use of 'IfInRange'

Expand Messages
  • John Shotsky
    I d like to use the If In Range command to make a decision how to process numbers. If it s within a certain range, I want to do one thing, and if it s not, I
    Message 1 of 10 , Mar 9, 2011
    • 0 Attachment
      I'd like to use the If In Range command to make a decision how to process
      numbers. If it's within a certain range, I want to do one thing, and if it's
      not, I want to process it differently. I don't quite understand how I get
      the number to be evaluated. Would you use a find first, then use
      ^$GetReSubstrings$ to capture the value of the whole number, followed by its
      decimal component as the second value? I want to use the IfInRange on the
      second value. Can someone that has used the command show me a working
      example? I can adapt to my needs if I see a working sample.



      An example of how this might be used is if a decimal number has 0-4 as the
      first number after a decimal point. (6.199) If it's within that range, I'd
      drop the decimal point and any decimals, thus rounding down to a whole
      number. (6) That would leave all the other decimals as needing to be rounded
      up to a whole number, such as 199.6, which would become 200.



      What is the best way to implement rounding on mixed numbers (different
      numbers of decimals, such as 1.34, 2.6666667, etc)? I assume you'd have to
      capture the whole number in its own variable, and increment it if the range
      of the first decimal is 5-9. (Not in the range 0-4, meaning the 'other'
      numbers from the ones already rounded down).



      Is there an easier way to do rounding?



      Regards,

      John

      RecipeTools site: http://recipetools.gotdns.com

      Beaverton Weather: http://shotsky.gotdns.com





      [Non-text portions of this message have been removed]
    • John Shotsky
      I came up with a solution that was a little easier than I thought it would be. Thought I d share it in case anyone else needs it. The key thing here is that
      Message 2 of 10 , Mar 9, 2011
      • 0 Attachment
        I came up with a solution that was a little easier than I thought it would
        be. Thought I'd share it in case anyone else needs it. The key thing here is
        that the decimals are not fixed length, so simple rounding may not work. The
        goal is to round to the nearest whole number, regardless of number of
        decimals.

        My dataset:
        Some text 17.9
        Some text 1.23456789
        15.567
        20.900000

        My clip:
        ;Round numbers based on first character after decimal point
        ^!Jump Doc_Start
        :Round
        ^!Find "(\d+)\.(\d)(\d+)*" IRS
        ^!IfError EndRound
        ^!SetArray %Value%=^$GetReSubstrings$
        ^!If "^%Value2%" => "5" Next ELSE Skip_1
        ^!Inc %Value1%
        ^!Replace "(\d+)\.(\d+)" >> "^%Value1%" RS
        ^!GoTo Round
        :EndRound

        Regards,
        John
        RecipeTools site: <http://recipetools.gotdns.com>
        http://recipetools.gotdns.com
        Beaverton Weather: <http://shotsky.gotdns.com> http://shotsky.gotdns.com

        From: ntb-clips@yahoogroups.com [mailto:ntb-clips@yahoogroups.com] On Behalf
        Of John Shotsky
        Sent: Wednesday, March 09, 2011 11:19
        To: ntb-clips@yahoogroups.com
        Subject: [Clip] Use of 'IfInRange'


        I'd like to use the If In Range command to make a decision how to process
        numbers. If it's within a certain range, I want to do one thing, and if it's
        not, I want to process it differently. I don't quite understand how I get
        the number to be evaluated. Would you use a find first, then use
        ^$GetReSubstrings$ to capture the value of the whole number, followed by its
        decimal component as the second value? I want to use the IfInRange on the
        second value. Can someone that has used the command show me a working
        example? I can adapt to my needs if I see a working sample.

        An example of how this might be used is if a decimal number has 0-4 as the
        first number after a decimal point. (6.199) If it's within that range, I'd
        drop the decimal point and any decimals, thus rounding down to a whole
        number. (6) That would leave all the other decimals as needing to be rounded
        up to a whole number, such as 199.6, which would become 200.

        What is the best way to implement rounding on mixed numbers (different
        numbers of decimals, such as 1.34, 2.6666667, etc)? I assume you'd have to
        capture the whole number in its own variable, and increment it if the range
        of the first decimal is 5-9. (Not in the range 0-4, meaning the 'other'
        numbers from the ones already rounded down).

        Is there an easier way to do rounding?

        Regards,

        John

        RecipeTools site: http://recipetools.gotdns.com

        Beaverton Weather: http://shotsky.gotdns.com

        [Non-text portions of this message have been removed]



        [Non-text portions of this message have been removed]
      • diodeom
        ... Simple rounding should work: ^!Jump 1 ^!Find d+ . d+ RS ^!IfError End ^!InsertText ^$Calc(ROUND(^$GetSelection$))$ ^!Goto Skip_-3
        Message 3 of 10 , Mar 9, 2011
        • 0 Attachment
          John Shotsky <jshotsky@...> wrote:
          >
          > The key thing here is
          > that the decimals are not fixed length, so simple rounding may not work. The
          > goal is to round to the nearest whole number, regardless of number of
          > decimals.
          >
          > My dataset:
          > Some text 17.9
          > Some text 1.23456789
          > 15.567
          > 20.900000
          >
          > My clip:
          > ;Round numbers based on first character after decimal point
          > ^!Jump Doc_Start
          > :Round
          > ^!Find "(\d+)\.(\d)(\d+)*" IRS
          > ^!IfError EndRound
          > ^!SetArray %Value%=^$GetReSubstrings$
          > ^!If "^%Value2%" => "5" Next ELSE Skip_1
          > ^!Inc %Value1%
          > ^!Replace "(\d+)\.(\d+)" >> "^%Value1%" RS
          > ^!GoTo Round
          > :EndRound
          >

          Simple rounding should work:

          ^!Jump 1
          ^!Find "\d+\.\d+" RS
          ^!IfError End
          ^!InsertText ^$Calc(ROUND(^$GetSelection$))$
          ^!Goto Skip_-3
        • John Shotsky
          Yes, it does work. Thanks! Regards, John RecipeTools site: http://recipetools.gotdns.com Beaverton Weather:
          Message 4 of 10 , Mar 9, 2011
          • 0 Attachment
            Yes, it does work. Thanks!

            Regards,
            John
            RecipeTools site: <http://recipetools.gotdns.com>
            http://recipetools.gotdns.com
            Beaverton Weather: <http://shotsky.gotdns.com> http://shotsky.gotdns.com

            From: ntb-clips@yahoogroups.com [mailto:ntb-clips@yahoogroups.com] On Behalf
            Of diodeom
            Sent: Wednesday, March 09, 2011 15:33
            To: ntb-clips@yahoogroups.com
            Subject: [Clip] Re: Use of 'IfInRange'


            John Shotsky <jshotsky@...> wrote:
            >
            > The key thing here is
            > that the decimals are not fixed length, so simple rounding may not work.
            The
            > goal is to round to the nearest whole number, regardless of number of
            > decimals.
            >
            > My dataset:
            > Some text 17.9
            > Some text 1.23456789
            > 15.567
            > 20.900000
            >
            > My clip:
            > ;Round numbers based on first character after decimal point
            > ^!Jump Doc_Start
            > :Round
            > ^!Find "(\d+)\.(\d)(\d+)*" IRS
            > ^!IfError EndRound
            > ^!SetArray %Value%=^$GetReSubstrings$
            > ^!If "^%Value2%" => "5" Next ELSE Skip_1
            > ^!Inc %Value1%
            > ^!Replace "(\d+)\.(\d+)" >> "^%Value1%" RS
            > ^!GoTo Round
            > :EndRound
            >

            Simple rounding should work:

            ^!Jump 1
            ^!Find "\d+\.\d+" RS
            ^!IfError End
            ^!InsertText ^$Calc(ROUND(^$GetSelection$))$
            ^!Goto Skip_-3



            [Non-text portions of this message have been removed]
          • flo.gehrke
            ... John, Given the subject... Take 199.6 pounds of flour, 6.199 pounds of rice, 1.34 pounds of salt and 2.6666667 pounds of sugar. Now you could check the
            Message 5 of 10 , Mar 10, 2011
            • 0 Attachment
              --- In ntb-clips@yahoogroups.com, "John Shotsky" <jshotsky@...> wrote:
              >
              > I'd like to use the If In Range command to make a decision
              > how to process numbers. If it's within a certain range, I want
              > to do one thing, and if it's not, I want to process it
              > differently. I don't quite understand how I get
              > the number to be evaluated (...) Can someone that has used the
              > command show me a working example?

              John,

              Given the subject...

              'Take 199.6 pounds of flour, 6.199 pounds of rice, 1.34 pounds of salt and 2.6666667 pounds of sugar.'

              Now you could check the first number after the decimal point with the following clip (click OK after each match):

              ^!Jump Doc_Start
              :Start
              ^!Find "\d{1,}\.(\d)\d{0,}" RS
              ^!IfError End
              ^!Set %dig%=^$GetReSubstrings$
              ^!IfInRange ^%dig% 0..4 True Else False
              :True
              ^!Info Yes, it's in that range!
              ^!Goto Start
              :False
              ^!Info No, it's not in that range!
              ^!Goto Start

              But I don't think this a better approach to rounding than the solution given by diodeom and what we've discussed in topic #21513 just a few weeks ago.

              Regards,
              Flo
            • diodeom
              ... For large files these time-consuming iterations could be cut approximately in half if confined only to numbers that require rounding up: ^!Jump 1 ^!Find
              Message 6 of 10 , Mar 10, 2011
              • 0 Attachment
                >
                > ^!Jump 1
                > ^!Find "\d+\.\d+" RS
                > ^!IfError End
                > ^!InsertText ^$Calc(ROUND(^$GetSelection$))$
                > ^!Goto Skip_-3
                >

                For large files these time-consuming iterations could be cut approximately in half if confined only to numbers that require rounding up:

                ^!Jump 1
                ^!Find "\d+(?=\.[5-9])" RS
                ^!IfError Done
                ^!InsertText ^$Calc(^$GetSelection$+1)$
                ^!Goto Skip_-3
                :Done
                ^!Replace "\d+\K\.\d+" >> "" WARS

                Similarly, when rounding to decimals:

                ^!Set %x%=^?{(H=3)Round to==10s^=1|_100ths^=2|1000ths^=3}
                ^!Set %y%=1^$StrFill(0;^%x%)$
                ^!Jump 1
                ^!Find "\d+\.\d{^%x%}[5-9]\d*+" RS
                ^!IfError Done
                ^!InsertText ^$Calc(ROUND(^$GetSelection$*^%y%)/^%y%;^%x%)$
                ^!Goto Skip_-3
                :Done
                ^!Replace "\d+\.\d{^%x%}\K\d+" >> "" WARS
              • John Shotsky
                Thanks, Flo, I wanted to see an example of proper usage of that command to see how to implement it. It turns out that my example was a poor one, but Dio s
                Message 7 of 10 , Mar 10, 2011
                • 0 Attachment
                  Thanks, Flo,



                  I wanted to see an example of proper usage of that command to see how to
                  implement it. It turns out that my example was a poor one, but Dio's
                  solution does work great for the example I provided. I have other needs that
                  aren't exactly the same, where this command will probably be used, and Round
                  cannot be used, since the 'break point' I'm looking for isn't at 5.



                  Consider how you'd handle converting decimals to fractions, when you are
                  restricted to fractions of 1/16 or larger. Only /16, /8 /4 /3 and /2 are
                  permitted. When a decimal falls between the natural break between these
                  fractions, what is the best way to determine which fraction should be used?
                  This is actually the problem I was trying to resolve in a better way than my
                  current kludge, which uses classes, but isn't accurate for numbers between
                  15/16 and the next whole number. If the decimal is closer to 15/16 than the
                  next whole number, I'd choose the fraction, but when it's closer to the
                  whole number, I'd want to round up to the whole number. After I played
                  around with it for a few hours, I decided I need a different approach, and
                  thought perhaps IfInRange would work better.



                  Regards,

                  John

                  RecipeTools site: <http://recipetools.gotdns.com>
                  http://recipetools.gotdns.com

                  Beaverton Weather: <http://shotsky.gotdns.com> http://shotsky.gotdns.com



                  From: ntb-clips@yahoogroups.com [mailto:ntb-clips@yahoogroups.com] On Behalf
                  Of flo.gehrke
                  Sent: Thursday, March 10, 2011 00:38
                  To: ntb-clips@yahoogroups.com
                  Subject: [Clip] Re: Use of 'IfInRange'





                  --- In ntb-clips@yahoogroups.com <mailto:ntb-clips%40yahoogroups.com> ,
                  "John Shotsky" <jshotsky@...> wrote:
                  >
                  > I'd like to use the If In Range command to make a decision
                  > how to process numbers. If it's within a certain range, I want
                  > to do one thing, and if it's not, I want to process it
                  > differently. I don't quite understand how I get
                  > the number to be evaluated (...) Can someone that has used the
                  > command show me a working example?

                  John,

                  Given the subject...

                  'Take 199.6 pounds of flour, 6.199 pounds of rice, 1.34 pounds of salt and
                  2.6666667 pounds of sugar.'

                  Now you could check the first number after the decimal point with the
                  following clip (click OK after each match):

                  ^!Jump Doc_Start
                  :Start
                  ^!Find "\d{1,}\.(\d)\d{0,}" RS
                  ^!IfError End
                  ^!Set %dig%=^$GetReSubstrings$
                  ^!IfInRange ^%dig% 0..4 True Else False
                  :True
                  ^!Info Yes, it's in that range!
                  ^!Goto Start
                  :False
                  ^!Info No, it's not in that range!
                  ^!Goto Start

                  But I don't think this a better approach to rounding than the solution given
                  by diodeom and what we've discussed in topic #21513 just a few weeks ago.

                  Regards,
                  Flo





                  [Non-text portions of this message have been removed]
                • John Shotsky
                  Thanks, again, Dio! Time is of consideration here, as some of my files are over 1M and take up to 1/2 hour to complete. I ve been concentrating on ways to cut
                  Message 8 of 10 , Mar 10, 2011
                  • 0 Attachment
                    Thanks, again, Dio!

                    Time is of consideration here, as some of my files are over 1M and take up
                    to 1/2 hour to complete. I've been concentrating on ways to cut processing
                    time, and one of those ways is in not capturing things that don't need to be
                    captured. It's easy to use parens to group things, but it takes some thought
                    to insert text in front of, or in the middle of a line without capturing
                    anything. \K is my friend here, but the look-aheads are less 'friendly' to
                    me.



                    I will certainly use what you've provided below, as it is similar to my
                    previous approach, where only the lines needing rounding up were processed
                    in the loop.



                    Regards,

                    John

                    RecipeTools site: <http://recipetools.gotdns.com>
                    http://recipetools.gotdns.com

                    Beaverton Weather: <http://shotsky.gotdns.com> http://shotsky.gotdns.com



                    From: ntb-clips@yahoogroups.com [mailto:ntb-clips@yahoogroups.com] On Behalf
                    Of diodeom
                    Sent: Thursday, March 10, 2011 05:55
                    To: ntb-clips@yahoogroups.com
                    Subject: [Clip] Re: Use of 'IfInRange'





                    >
                    > ^!Jump 1
                    > ^!Find "\d+\.\d+" RS
                    > ^!IfError End
                    > ^!InsertText ^$Calc(ROUND(^$GetSelection$))$
                    > ^!Goto Skip_-3
                    >

                    For large files these time-consuming iterations could be cut approximately
                    in half if confined only to numbers that require rounding up:

                    ^!Jump 1
                    ^!Find "\d+(?=\.[5-9])" RS
                    ^!IfError Done
                    ^!InsertText ^$Calc(^$GetSelection$+1)$
                    ^!Goto Skip_-3
                    :Done
                    ^!Replace "\d+\K\.\d+" >> "" WARS

                    Similarly, when rounding to decimals:

                    ^!Set %x%=^?{(H=3)Round to==10s^=1|_100ths^=2|1000ths^=3}
                    ^!Set %y%=1^$StrFill(0;^%x%)$
                    ^!Jump 1
                    ^!Find "\d+\.\d{^%x%}[5-9]\d*+" RS
                    ^!IfError Done
                    ^!InsertText ^$Calc(ROUND(^$GetSelection$*^%y%)/^%y%;^%x%)$
                    ^!Goto Skip_-3
                    :Done
                    ^!Replace "\d+\.\d{^%x%}\K\d+" >> "" WARS





                    [Non-text portions of this message have been removed]
                  • diodeom
                    ... No need to bother with ROUND at all: ^!Set %x%=^?{(H=3)Round to==10s^=1|_100ths^=2|1000ths^=3} ^!Jump 1 ^!Find d+ . d{^%x%}[5-9] d*+ RS ^!IfError Done
                    Message 9 of 10 , Mar 10, 2011
                    • 0 Attachment
                      >
                      > Similarly, when rounding to decimals:
                      >

                      No need to bother with ROUND at all:

                      ^!Set %x%=^?{(H=3)Round to==10s^=1|_100ths^=2|1000ths^=3}
                      ^!Jump 1
                      ^!Find "\d+\.\d{^%x%}[5-9]\d*+" RS
                      ^!IfError Done
                      ^!InsertText ^$Calc(^$GetSelection$;^%x%)$
                      ^!Goto Skip_-3
                      :Done
                      ^!Replace "\d+\.\d{^%x%}\K\d+" >> "" WARS
                    • Art Kocsis
                      John, To find the nearest fraction is just an extension of the normal technique for rounding: adding .5 to the number and truncating. In your case, extract the
                      Message 10 of 10 , Mar 10, 2011
                      • 0 Attachment
                        John,

                        To find the nearest fraction is just an extension of the normal technique for
                        rounding: adding .5 to the number and truncating.

                        In your case, extract the decimal portion (x), multiply by 16, add .5 and then
                        truncate:

                        Int(x * 16 + 0.5)

                        The result will be the nearest 16th to your original number.

                        This is similar to the fence post problem in that there are 17 possible results
                        for the 16 intervals: 0 thru 16. I would create a 17 element static array
                        containing
                        the strings that you want to display for each value (such as "1/16", "1/8",
                        "3/16", "1/4", etc), the 17th one being blank. Use the result+1 to index
                        into the array. You would only need to test for when the result equals 16 in
                        which case you need to add one to the original integer.

                        This should be faster than a lot of tests for 16 conditions. [Remember to turn
                        screen update off <g>]

                        HTH

                        Namaste', Art



                        At 03/10/2011 05:59, John wrote:
                        <snip>
                        >Consider how you'd handle converting decimals to fractions, when you are
                        >restricted to fractions of 1/16 or larger. Only /16, /8 /4 /3 and /2 are
                        >permitted. When a decimal falls between the natural break between these
                        >fractions, what is the best way to determine which fraction should be used?
                        >This is actually the problem I was trying to resolve in a better way than my
                        >current kludge, which uses classes, but isn't accurate for numbers between
                        >15/16 and the next whole number. If the decimal is closer to 15/16 than the
                        >next whole number, I'd choose the fraction, but when it's closer to the
                        >whole number, I'd want to round up to the whole number. After I played
                        >around with it for a few hours, I decided I need a different approach, and
                        >thought perhaps IfInRange would work better.
                      Your message has been successfully submitted and would be delivered to recipients shortly.