Results 1 to 15 of 15

Thread: [RESOLVED] Logic Help (Recode Select Case to Function)

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    602

    Resolved [RESOLVED] Logic Help (Recode Select Case to Function)

    I have the following code that uses a Select Case Block to alter a value.

    I can see a pattern, but for the life of me, I cannot come up with a simple Function to replace it.

    If this were the only cases in the Select Case Block, I would use this and be done with it,
    but there are many more cases to enter (same pattern).

    As always, help would be appreciated.

    Code:
    Private Sub Command2_Click()
    
        Const STD_COL_WIDTH As Long = 12
        
        Dim myFactor As Single
    
        Dim availableSpace As Long
        Dim thisColWidth As Long
    
        availableSpace = 46
        thisColWidth = 24
    
        myFactor = (availableSpace / thisColWidth)
        
        MsgBox "myfactor (Before) = " & myFactor
    
        Select Case myFactor
            Case Is <= (12 / STD_COL_WIDTH)
                myFactor = (8 / STD_COL_WIDTH)
            Case Is <= (16 / STD_COL_WIDTH)
                myFactor = (12 / STD_COL_WIDTH)
            Case Is <= (20 / STD_COL_WIDTH)
                myFactor = (16 / STD_COL_WIDTH)
            Case Is <= (24 / STD_COL_WIDTH)
                myFactor = (20 / STD_COL_WIDTH)
            Case Is <= (28 / STD_COL_WIDTH)
                myFactor = (24 / STD_COL_WIDTH)
            Case Is <= (32 / STD_COL_WIDTH)
                myFactor = (28 / STD_COL_WIDTH)
            Case Is <= (36 / STD_COL_WIDTH)
                myFactor = (32 / STD_COL_WIDTH)
            Case Is <= (40 / STD_COL_WIDTH)
                myFactor = (36 / STD_COL_WIDTH)
            Case Is <= (44 / STD_COL_WIDTH)
                myFactor = (40 / STD_COL_WIDTH)
            Case Is <= (48 / STD_COL_WIDTH)
                myFactor = (44 / STD_COL_WIDTH)
            Case Is <= (52 / STD_COL_WIDTH)
                myFactor = (48 / STD_COL_WIDTH)
        End Select
        
        MsgBox "myfactor (After) = " & myFactor
    
    End Sub

  2. #2
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,872

    Re: Logic Help (Recode Select Case to Function)

    The difference between the Case and the assignment is 4
    So why not:
    myFactor = (myFactor - 4)/ STD_COL_WIDTH

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    602

    Re: Logic Help (Recode Select Case to Function)

    Thanks Arnoutdv

    I tried as you suggested, but the output is incorrect.
    Code:
    Private Sub Command3_Click()
    
        Const STD_COL_WIDTH As Long = 12
        
        Dim myFactor As Single
    
        Dim availableSpace As Long
        Dim thisColWidth As Long
    
        availableSpace = 46
        thisColWidth = 24
    
        myFactor = (availableSpace / thisColWidth)
        
        MsgBox "myfactor (Before) = " & myFactor
        
        myFactor = (myFactor - 4) / STD_COL_WIDTH
        
        MsgBox "myfactor (After) = " & myFactor
    
    End Sub
    Last edited by mms_; Feb 24th, 2021 at 12:23 PM.

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Logic Help (Recode Select Case to Function)

    Yes, Arnoutdv didn't see that myFactor is not always a difference of 4 since it covers a difference within a range of 4. Also, it isn't actually a difference of 4 from myFactor, since myFactor is the result of a division.
    For instance your first case statement is actually saying if myFactor is less than or equal to 1, make it .6666...


    It is more of a floor function which could be handled with a Mod operation if you were dealing with Integers. Since you're dealing with Singles I would have to look at the code more to understand the relationship between thisColWidth and STD_COL_WIDTH in relation to availableSpace.
    Last edited by passel; Feb 24th, 2021 at 12:39 PM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  5. #5
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Logic Help (Recode Select Case to Function)

    You could try a function like this.
    Don't know that it will cover all cases. 12 in the function is the STD_COL_WIDTH value, so you may want to add that Constant. I just wrote this quick and didn't do extensive testing on it.
    Code:
    Option Explicit
    
    Private Sub Command1_Click()
      Debug.Print NearestLessSize(46, 24)
    End Sub
    
    Private Function NearestLessSize(avSp As Long, thisCol As Long) As Single
      Dim sz As Long
      sz = (avSp / thisCol) * 12
      NearestLessSize = (sz - sz Mod 4) / 12!
      
    End Function
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    602

    Re: Logic Help (Recode Select Case to Function)

    Thank you passel!

    Your Function works perfectly!
    It works for any values I test with, and as far as I can tell, it will work correctly with all input values period.

  7. #7
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Quote Originally Posted by mms_ View Post
    I can see a pattern ...

    Code:
        Select Case myFactor
            Case Is <= (12 / STD_COL_WIDTH): myFactor = (8 / STD_COL_WIDTH)
            Case Is <= (16 / STD_COL_WIDTH): myFactor = (12 / STD_COL_WIDTH)
            Case Is <= (20 / STD_COL_WIDTH): myFactor = (16 / STD_COL_WIDTH)
            '...
    As for "the pattern" you already have "a hunch" about...

    If we remove the (constant) STD_COL_WIDTH term from the above,
    it will become even more pronounced, what the pattern is...

    Code:
        Select Case Value
            Case Is < 12: Value = 8
            Case Is < 16: Value = 12
            Case Is < 20: Value = 16
            '...
    So the above ensures, that:
    - a Value in the interval [12, 16) will be "clamped" to 12
    - a Value in the interval [16, 20) will be "clamped" to 16
    - a.s.o.

    So, you want to ensure (on a free-wheeling Input-Value),
    that it always comes out as "the nearest multiple of 4".

    And the (IMO) simplest way to ensure that, is the following:
    Value = Int(Value / 4) * 4

    Or expressed in a more generically usable Function:
    Code:
    Function ClampToMultiplesOf(MFac, Value)
      ClampToMultiplesOf = Int(Value / MFac) * MFac
    End Function
    Usage then (probably):
    Code:
      myFactor = ClampToMultiplesOf(4, availableSpace / thisColWidth) 
      myFactor = IIF(myFactor < 8, 8, myFactor) / STD_COL_WIDTH
    But currently we can only guess, what you want to do with "myFactor" afterwards...
    (a little bit more background would have been nice).

    HTH

    Olaf
    Last edited by Schmidt; Feb 25th, 2021 at 05:32 AM.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    602

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Thank you Schmidt

    I believe I see what you are doing, but I can't get the correct output with your code/function.
    (I don't understand what the 8 is in your Usage example)

    I add two text boxes to a form, and set Text1.Text = 46 and Text2.Text = 24

    If I run my original Select Case routine, I get output as 1.916667 (Before) and 1.666666 (After)
    If I run passel's code, I get same output.
    If I run your code, I get output as 1.916667 (Before) and 0.666666 (After)

    Code:
    Private Sub Command6_Click()
    
        ' Using Schmidt's code
        
        Const STD_COL_WIDTH As Long = 12
        
        Dim myFactor As Single
    
        Dim availableSpace As Long
        Dim thisColWidth As Long
    
        availableSpace = Val(Text1.Text)
        thisColWidth = Val(Text2.Text)
    
        myFactor = (availableSpace / thisColWidth)
        
        MsgBox "myfactor (Before) = " & myFactor
        
        myFactor = ClampToMultiplesOf(4, availableSpace / thisColWidth)
        myFactor = IIf(myFactor < 8, 8, myFactor) / STD_COL_WIDTH
        
        MsgBox "myfactor (After) = " & myFactor
    
    End Sub
    
    Function ClampToMultiplesOf(MFac, Value)
      ClampToMultiplesOf = Int(Value / MFac) * MFac
    End Function

  9. #9
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Quote Originally Posted by mms_ View Post
    Thank you Schmidt

    I believe I see what you are doing, but I can't get the correct output with your code/function.
    Ah, yes - forgot to multiply the input with the Std-Col-Width...

    Here is the adjusted "usage-code" (in a function, similar to passels):
    Code:
    Function NearestLessSize3(AvSp, ColW, Optional ByVal StdW& = 12) As Single
      Dim sz As Long
          sz = ClampToMultiplesOf(4, StdW / ColW * AvSp)
      NearestLessSize3 = IIf(sz < 8, 8, sz) / StdW
    End Function
    And here is some test-code for all 3 variants (which all differ in their results, more or less):
    Code:
    Private Sub Form_Load()
      Debug.Print "AvailSp", "mms_", "passel", "olaf"
      
      'test-loop with Avail-Space from 0 to 46
      Dim AvSp As Long:   Const ColW As Long = 24
      For AvSp = 0 To 46
        Debug.Print AvSp, CLng(ColW * NearestLessSize1(AvSp, ColW)), _
                          CLng(ColW * NearestLessSize2(AvSp, ColW)), _
                          CLng(ColW * NearestLessSize3(AvSp, ColW))
      Next
    End Sub
    
    Function NearestLessSize1(AvSp, ColW, Optional ByVal StdW& = 12) As Single
      Select Case AvSp / ColW
        Case Is <= (12 / StdW): NearestLessSize1 = (8 / StdW)
        Case Is <= (16 / StdW): NearestLessSize1 = (12 / StdW)
        Case Is <= (20 / StdW): NearestLessSize1 = (16 / StdW)
        Case Is <= (24 / StdW): NearestLessSize1 = (20 / StdW)
        Case Is <= (28 / StdW): NearestLessSize1 = (24 / StdW)
        Case Is <= (32 / StdW): NearestLessSize1 = (28 / StdW)
        Case Is <= (36 / StdW): NearestLessSize1 = (32 / StdW)
        Case Is <= (40 / StdW): NearestLessSize1 = (36 / StdW)
        Case Is <= (44 / StdW): NearestLessSize1 = (40 / StdW)
        Case Is <= (48 / StdW): NearestLessSize1 = (44 / StdW)
        Case Is <= (52 / StdW): NearestLessSize1 = (48 / StdW)
      End Select
    End Function
    
    Function NearestLessSize2(AvSp, ColW, Optional ByVal StdW& = 12) As Single
      Dim sz As Long
          sz = (AvSp / ColW) * StdW
      NearestLessSize2 = (sz - sz Mod 4) / StdW
    End Function
    
    Function NearestLessSize3(AvSp, ColW, Optional ByVal StdW& = 12) As Single
      Dim sz As Long
          sz = ClampToMultiplesOf(4, StdW / ColW * AvSp)
      NearestLessSize3 = IIf(sz < 8, 8, sz) / StdW
    End Function
    
    Function ClampToMultiplesOf(MFac, Value)
      ClampToMultiplesOf = Int(Value / MFac) * MFac
    End Function
    So the above Function-calls (NearestLessSize1 to 3) generate your new Factor -
    but we still don't know what you want to use this factor for in the end...
    (the test-code assumes, that you plan to multiply the current ColWidth with it...)

    Anyways, the Debug-Output of the test-snippet is as follows (yours in column2 and mine in column4 are closest):
    Code:
    AvailSp       mms_          passel        olaf
     0             16            0             16 
     1             16            0             16 
     2             16            0             16 
     3             16            0             16 
     4             16            0             16 
     5             16            0             16 
     6             16            0             16 
     7             16            8             16 
     8             16            8             16 
     9             16            8             16 
     10            16            8             16 
     11            16            8             16 
     12            16            8             16 
     13            16            8             16 
     14            16            8             16 
     15            16            16            16 
     16            16            16            16 
     17            16            16            16 
     18            16            16            16 
     19            16            16            16 
     20            16            16            16 
     21            16            16            16 
     22            16            16            16 
     23            16            24            16 
     24            16            24            24 
     25            24            24            24 
     26            24            24            24 
     27            24            24            24 
     28            24            24            24 
     29            24            24            24 
     30            24            24            24 
     31            24            32            24 
     32            24            32            32 
     33            32            32            32 
     34            32            32            32 
     35            32            32            32 
     36            32            32            32 
     37            32            32            32 
     38            32            32            32 
     39            32            40            32 
     40            32            40            40 
     41            40            40            40 
     42            40            40            40 
     43            40            40            40 
     44            40            40            40 
     45            40            40            40 
     46            40            40            40
    HTH

    Olaf

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    602

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Thanks for your reply Schmidt

    but we still don't know what you want to use this factor for in the end...
    I am using it to reposition GDI+ drawn objects on screen/printer/pdf (depending on how much space is available) as below:

    Code:
    myFactor = (availableSpace / thisColWidth)
    myFactor = myFactor * thisColWidth
    myFactor = (myFactor - (myFactor Mod 4)) / thisColWidth         'passel's code (in-line)
    
    '< do stuff >
    
    ' Re-position object (via .Position.col)
    Obj(j).Position.col = _
        Obj(j).Position.col + _
            Round(GetDurDecimal(Obj(k - 1)) * myFactor * thisColWidth, 0)
    In looking at the code above, I think I am unnecessarily multiplying and dividing thisColWidth
    It appears 4 times in the above code (divide, multiply, divide, multiply)
    I probably can get rid of thisColWidth all together???

    On the weekend, I will try to wrap my head around the outputs and see which column is correct.
    Last edited by mms_; Feb 25th, 2021 at 04:27 PM.

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    602

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    So my code can be paired down to this: (nice and simple)
    Code:
    modulusDivisor = 4  'what is this number actually??
    
    myFactor = (availableSpace)
    myFactor = (myFactor - (myFactor Mod modulusDivisor))   'passel (in-line)
    
    '< do stuff >
    
    ' Re-position object (via .Position.col)
    Obj(j).Position.col = _
        Obj(j).Position.col + _
            Round(GetDurDecimal(Obj(k - 1)) * myFactor, 0)
    ... but I don't really understand what my modulusDivisor actally IS
    I've noticed that 4, 8, 16, 32, 64 each work as values for modulusDivisor in different scenarios
    Another pattern

    Now I'll try to figure out why close (but sometimes different) results in Olaf's comparison routine
    Last edited by mms_; Feb 28th, 2021 at 02:00 AM.

  12. #12
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    The Mod operator does an integer divide and returns the integer remainder.
    If you subtract the remainder from the original number that will "round down" the original number to a multiple of the divisor.
    So, doing that with 4, will give you a multiple of 4, i.e. 0, 4, 8, 12, etc...
    0 / 4 = 0 with a remainder of 0 : 0 - 0 = 0
    1 / 4 = 0 with a remainder of 1 : 1 - 1 = 0
    2 / 4 = 0 with a remainder of 2 : 2 - 2 = 0
    3 / 4 = 0 with a remainder of 3 : 3 - 3 = 0
    4 / 4 = 1 with a remainder of 0 : 4 - 0 = 4
    5 / 4 = 1 with a remainder of 1 : 5 - 1 = 4
    6 / 4 = 1 with a remainder of 2 : 6 - 2 = 4
    7 / 4 = 1 with a remainder of 3 : 7 - 3 = 4
    8 / 4 = 2 with a remainder of 0 : 8 - 0 = 8
    9 / 4 = 2 with a remainder of 1 : 9 - 1 = 8
    ... etc.

    If you did a Mod 5, then you would get 0, 5, 10, 15...
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  13. #13
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Quote Originally Posted by mms_ View Post
    modulusDivisor = 4 'what is this number actually??

    myFactor = (availableSpace)
    myFactor = (myFactor - (myFactor Mod modulusDivisor))
    As for your question ("what is this number")...

    I think, if you reduce the 3 lines above to the one-liner below...
    Code:
    myFactor = ClampToMultiplesOf(4, availableSpace)
    then you got identical working code - and also your answer.

    (well-named functions can save lives... erm... comments)

    Olaf

  14. #14
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Quote Originally Posted by Schmidt View Post
    (well-named functions can save lives... erm... comments)
    https://en.wikipedia.org/wiki/Clamping_(graphics)

    "Clamp" first I heard from John Carmack of id software fame discussing Quake (or Doom) sources. . .

    cheers,
    </wqw>

  15. #15
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Logic Help (Recode Select Case to Function)

    Quote Originally Posted by wqweto View Post
    https://en.wikipedia.org/wiki/Clamping_(graphics)

    "Clamp" first I heard from John Carmack of id software fame discussing Quake (or Doom) sources. . .
    I think the function-name makes sense also in its normal english meaning (for "clamp" or "clamping" or "boxing smth. in").

    ClampToMultiplesOf(4, availableSpace)

    Red-text = left side (min) ... and blue text the right side (max) of "the clamp" (interval).

    Olaf

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width