cerdmann
asked on
Comparing Numbers
I need to compare numbers quickly from the leftmost digit to the right.
Example:
187787852
is equivallent to
1877814481
up to 18778
I know I can do this with strings, however I would like to do it purely mathematically.
Any ideas?
Example:
187787852
is equivallent to
1877814481
up to 18778
I know I can do this with strings, however I would like to do it purely mathematically.
Any ideas?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Some like this?
Function LShift(iVariable As Integer, _
iNumbits As Integer) As Integer
LShift = iVariable * (2 ^ iNumbits)
End Function
Function RShift(iVariable As Integer, _
iNumbits As Integer) As Integer
RShift = iVariable \ (2 ^ iNumbits)
End Function
Function LShift(iVariable As Integer, _
iNumbits As Integer) As Integer
LShift = iVariable * (2 ^ iNumbits)
End Function
Function RShift(iVariable As Integer, _
iNumbits As Integer) As Integer
RShift = iVariable \ (2 ^ iNumbits)
End Function
ASKER
I already saw that article when I was researching this question however, I have never worked at the bit level and could use some help implementing it in my code.
Here is what I have thus far, just for switching between base 10 and base 8 (I know, I am using strings, but these functions will be rarily used)
Option Explicit
Private Sub Form_Load()
Debug.Print b8ConverttoBase10("1877814 481")
Debug.Print b8ConverttoBase8("1.63.100 .1")
End Sub
' ========================== ========== ========== ========== =========
' b8ConverttoString
' ========================== ========== ========== ========== =========
Public Function b8ConverttoBase10( _
ByVal Base8Number As Variant) As String
On Error GoTo ErrorHandler
Dim Base8String As String
Dim Base8Level() As String
Dim Base10Level() As String
Dim Levels As Long
Dim ArrayCounter As Long
Dim vntDecValue As Variant
Base8String = CStr(Base8Number)
Base8Level = Split(Base8String, "8")
Levels = UBound(Base8Level)
ReDim Base10Level(Levels)
For ArrayCounter = 0 To Levels
If Base8Level(ArrayCounter) <> "" Then
Base10Level(ArrayCounter) = CStr(CDec("&o" & Base8Level(ArrayCounter)))
End If
Next
b8ConverttoBase10 = Join(Base10Level(), ".")
Exit Function
ErrorHandler:
Err.Raise Err.Number, "b8ConverttoString", Err.Description
End Function
' ========================== ========== ========== ========== =========
' b8ConverttoBase8
' ========================== ========== ========== ========== =========
Public Function b8ConverttoBase8( _
ByVal Base10String As String) As Variant
On Error GoTo ErrorHandler
Dim Base8Level() As String
Dim Base10Level() As String
Dim Levels As Long
Dim ArrayCounter As Long
Dim Convert As Variant
Base10Level = Split(Base10String, ".")
Levels = UBound(Base10Level)
ReDim Base8Level(Levels)
For ArrayCounter = 0 To Levels
Base8Level(ArrayCounter) = Oct$(Base10Level(ArrayCoun ter))
Next
Convert = CDec(Join(Base8Level(), "8"))
b8ConverttoBase8 = Convert
Exit Function
ErrorHandler:
Err.Raise Err.Number, "b8ConverttoBase8", Err.Description
End Function
Here is what I have thus far, just for switching between base 10 and base 8 (I know, I am using strings, but these functions will be rarily used)
Option Explicit
Private Sub Form_Load()
Debug.Print b8ConverttoBase10("1877814
Debug.Print b8ConverttoBase8("1.63.100
End Sub
' ==========================
' b8ConverttoString
' ==========================
Public Function b8ConverttoBase10( _
ByVal Base8Number As Variant) As String
On Error GoTo ErrorHandler
Dim Base8String As String
Dim Base8Level() As String
Dim Base10Level() As String
Dim Levels As Long
Dim ArrayCounter As Long
Dim vntDecValue As Variant
Base8String = CStr(Base8Number)
Base8Level = Split(Base8String, "8")
Levels = UBound(Base8Level)
ReDim Base10Level(Levels)
For ArrayCounter = 0 To Levels
If Base8Level(ArrayCounter) <> "" Then
Base10Level(ArrayCounter) = CStr(CDec("&o" & Base8Level(ArrayCounter)))
End If
Next
b8ConverttoBase10 = Join(Base10Level(), ".")
Exit Function
ErrorHandler:
Err.Raise Err.Number, "b8ConverttoString", Err.Description
End Function
' ==========================
' b8ConverttoBase8
' ==========================
Public Function b8ConverttoBase8( _
ByVal Base10String As String) As Variant
On Error GoTo ErrorHandler
Dim Base8Level() As String
Dim Base10Level() As String
Dim Levels As Long
Dim ArrayCounter As Long
Dim Convert As Variant
Base10Level = Split(Base10String, ".")
Levels = UBound(Base10Level)
ReDim Base8Level(Levels)
For ArrayCounter = 0 To Levels
Base8Level(ArrayCounter) = Oct$(Base10Level(ArrayCoun
Next
Convert = CDec(Join(Base8Level(), "8"))
b8ConverttoBase8 = Convert
Exit Function
ErrorHandler:
Err.Raise Err.Number, "b8ConverttoBase8", Err.Description
End Function
Hi, why not convert it to a string, then do the comparison? Would this be much simpler and more readable than using bit manipulation? If I were you I would split the string into an array:
Dim arr() as string
Dim lngIndex as long
arr = split("1877814481","8")
for lngIndex = lbound(arr) to ubound(arr)
msgbox "Node" & arr(lngIndex)
next
To compare two to see if they have the same parents, just figure out which one is smaller, then iterate through both arrays until one of the elements is different.
Zaphod.
Dim arr() as string
Dim lngIndex as long
arr = split("1877814481","8")
for lngIndex = lbound(arr) to ubound(arr)
msgbox "Node" & arr(lngIndex)
next
To compare two to see if they have the same parents, just figure out which one is smaller, then iterate through both arrays until one of the elements is different.
Zaphod.
BTW, I doubt you are going to find a way to get parent, or get root, purely mathematically. Your number is not a number, it is a sequence of numbers, and as such you should probably treat it as such in code.
Zaphod.
Zaphod.
Hi!
Is this string-cum-numbers mrthod acceptable:
Dim p As Double
p = 1860000111
MsgBox "Original number: " & p
For i = 0 To 5 'For 1st 5 digits
result = p \ 10 ^ (Len(p) + 1 - i)
MsgBox result
p = p - result * 10 ^ (Len(p) + 1 - i)
Next i
That's it!
glass cookie : )
Is this string-cum-numbers mrthod acceptable:
Dim p As Double
p = 1860000111
MsgBox "Original number: " & p
For i = 0 To 5 'For 1st 5 digits
result = p \ 10 ^ (Len(p) + 1 - i)
MsgBox result
p = p - result * 10 ^ (Len(p) + 1 - i)
Next i
That's it!
glass cookie : )
hi
I agree with Z_B......
do your tests and compare part with string array
approach...then convert to numbers of whatever base
to continue.
leo
I agree with Z_B......
do your tests and compare part with string array
approach...then convert to numbers of whatever base
to continue.
leo
ASKER
I think we are going to try a different approach. Instead of base 8 I think we will limit ourselves to spacing within the number (hhggffeeddccbbaaaa).
Top node would be aaaa followed by bb by cc etc..
The problem is that we only get 7 levels of 99 and a top level of 9999 which actually shouldn't be too big of a problem.
If I make these changes, should I be able to write the functions for manipulating these numbers purely with mathematics?
Top node would be aaaa followed by bb by cc etc..
The problem is that we only get 7 levels of 99 and a top level of 9999 which actually shouldn't be too big of a problem.
If I make these changes, should I be able to write the functions for manipulating these numbers purely with mathematics?
If you do it that way and you have the parent to the right of the child, then you should be able to do everything mathematically, just be careful, the limit in VB for a long is 2 billion, 2,000,000,000, so you can only have 3 levels in your tree.
Zaphod.
Zaphod.
ASKER
To find each level now becomes a simple modulus operation.
12080001 =
1
|
8
|
12
12080001 mod 10000 = 1
((12080001 mod 1000000) - (12080001 mod 10000))/10000 = 8
((12080001 mod 100000000) - (12080001 mod 1000000))/1000000 = 12
12080001 =
1
|
8
|
12
12080001 mod 10000 = 1
((12080001 mod 1000000) - (12080001 mod 10000))/10000 = 8
((12080001 mod 100000000) - (12080001 mod 1000000))/1000000 = 12
ASKER
We use SQL Server 2000 BigInt with a VB variant cast with the cdec() command
ASKER
Zaphod helped the most towards determining the right path, so I am awarding the points to him. Thanks for everyone's help.
ASKER
For example 187787852 = 1.63.7.42
(use the 8's as the decimal and clng(&o) the intermediary numbers to get the above.
Also,
1877814481 = 1.63.100.1
So these 2 numbers both fall under the node 1.63 (18778)
Instead of converting them to strings I would like to do the following functions (Example uses 1877814481):
Get parent 144 (100)
Get root 1 (1)
Get common parent (Example given in my first question)
I guess mathematically was incorrect. I should have said programmatically not using strings.
I am storing all base 8 numbers as variants cast from a SQL BigInt via cdec().
Could you somehow left shift the bits so that they line up and then do a bitwise comparison? I have no idea how to do this, but my research has given me this idea.