Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Isolate part of a number 1

Status
Not open for further replies.

philipad

Technical User
Feb 12, 2006
23
CY
hi all

If I have a set of numbers for example 2504, 8903, 5602 is there a way to get the last two digits so I get 04,03,02?

thanks
 
Convert to string, then take Right two charactors.
Example below

Dim A As Integer
Dim B As String
A = 2504
B = A
B = Right(B, 2)
A = Val(B)
 
a=2504
b=a mod 100

so you still have it as a number.
 
TheNumber=8903

Debug.? Format$(((TheNumber/100)-(Int(TheNumber/100)))*100,"00")
 
Yuck. If you are going to use Format$, then

Format$(TheNumber Mod 100, "00")

is a much cleaner version (and should make tsh73 happy ;-) )

However, it is dramatically slower than the Right solution (which would itself be a fraction faster than it is if it was Right$)
 
I don't see what is "Yuck" about it.

It is a general basic function, which I use on large numbers (12 digit billing numbers such as "200602250029") as well as small number ranges (0 to x), showing an example on how to also handle this with the Format$ function, though not being a specific to the OP's samples.

-The MOD will not work on the larger numbers.
-The Right$ needs extra validation if the number is a single digit:
If LenB(b) = 2 Then b = "0" & b

(It also needs to use INT() if the number may have decimals, if that condition would ever apply)

The MOD and the additional validation is fastest against the sample data.

JFF:
-MOD With Validation (using 8923/8903): 0.07/0.13
-RIGHT$ with out Validation : 0.11
-MOD with FORMAT$: 0.25
-FORMAT$ and INT: 0.43

I used the QP with an average of five, one million loops.

My goodness. 0.43 / 5,000,000
That's the difference between "Yuck" and not "Yuck"!?

I was just posting another example, which will also work for a wider range of values than the RIGHT$ or MOD do, even though not streamlined to the OP's samples.

Saying that it is maybe under certain circumstances not efficient enough, as when dealing with a whole lot of numbers, or when the proceedure is already doing extremely intensive amount of work and extreme speed is needed, my be right.

But, come on, to say the code I posted is "Yuck", my goodness, is going little too far.
 
Ok. Maybe not 'Yuck' - but certainly overspecified for what the OP seems to be asking (IMO)

(although I don't seem to agree with your timings; a compiled version of my standard timing rig tested the various options on my AMD Athlon 2800+ XP Pro box - for 5000000 iterations the FORMAT$/INT solution took over 7.5 seconds whilst the Right$ solution took less than 2)
 

5,000,000

I did write:
>I used the QP with an average of five, one million loops.
And then the next line:
>0.43 / 5,000,000

That should have been:

0.43 / 1,000,000

Your right about the timing. I changed my outer loop to get through the testing faster and made a typo.
So, your timing looks more real.

But then still:
7.5 / 5,000,000 (or 1.5 / 1,000,000)

I guess there are many many areas all the time where code can be [re]written to be more efficient in this minor range, and, unless it is an intensive proceedure, we could easily and unnecessarily create an over-kill of Optimized/Efficient Code versus it being practical and reusable (newly typed and optimized code for each situation vs. 10 functions doing similar tasks but used according to the need of efficiency and job task vs. fewer functions handling a reasonable variety ranges at the sacrifice of speed - speed diffrerences which may never ever be noticed)
On the other side, we could write a proceedure which does too much, causing it to be too slow and hard to interpet, making it a headach to use. But you know all this far better than I do.

Just for the record, this is similar to what I used to time it:
Code:
    Dim StartTicks  As Currency
    Dim StopTicks   As Currency
    Dim Frequency   As Currency
    Dim i           As Long
    Dim a As Long
    Dim b As String
    a = 2504

    QueryPerformanceFrequency Frequency
    QueryPerformanceCounter StartTicks

    For i= 1 To 1000000
         b = Format$(((a / 100) - (Int(a / 100))) * 100, "00")
         'b = Right$(a, 2)
    Next i
    
    QueryPerformanceCounter StopTicks
    MsgBox (StopTicks - StartTicks) / Frequency
 
Yep, that's pretty close to mine - except I also use an 'empty' loop so that I can subtract the overhead of the loop itself from the timings. In this case that gave me:
Code:
[blue]Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long


Private Sub mysub()
    ' QP supporting declares
    Dim myFreq As Currency
    Dim myStart As Currency
    Dim myStop As Currency
    Dim TotalTime As Double

    ' Main declares
    Dim x As Long
    Dim maxloop As Long
    Dim lp As Long
    Dim result As String
    Dim BaseTime As Long
    Dim strMsg As String
    
    maxloop = Text1.Text
    
    QueryPerformanceFrequency myFreq
    
    x = 2048 'random data sample
        
        
    ' Base time
    QueryPerformanceCounter myStart
    For lp = 1 To maxloop
        result = ""
    Next
    QueryPerformanceCounter myStop
    BaseTime = CDbl((myStop - myStart) / myFreq)
    
    ' OK - now all the things we really want to time
    
    QueryPerformanceCounter myStart
    For lp = 1 To maxloop
        result = Right(x, 2)
    Next
    QueryPerformanceCounter myStop
    strMsg = "Right: " & CDbl((myStop - myStart) / myFreq) - BaseTime
    
    
    QueryPerformanceCounter myStart
    For lp = 1 To maxloop
        result = Right$(x, 2)
    Next
    QueryPerformanceCounter myStop
    strMsg = strMsg + vbCrLf + "Right$: " & CDbl((myStop - myStart) / myFreq) - BaseTime
    
    QueryPerformanceCounter myStart
    For lp = 1 To maxloop
        result = Format$(((x / 100) - (Int(x / 100))) * 100, "00")
    Next
    QueryPerformanceCounter myStop
    strMsg = strMsg + vbCrLf + "Format INT version: " & CDbl((myStop - myStart) / myFreq) - BaseTime
    
    QueryPerformanceCounter myStart
    For lp = 1 To maxloop
        result = Format$(x Mod 100, "00")
    Next
    QueryPerformanceCounter myStop
    strMsg = strMsg + vbCrLf + "Format MOD version: " & CDbl((myStop - myStart) / myFreq) - BaseTime
    
    MsgBox strMsg

End Sub[/blue]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top