I have a device that contains 64 bit number (Double) parameters. I can read its Double parameters using Modbus protocol in two parts. So I split the 64 bit number to two 32 bit numbers using bitwise operation.
Example: 2289225.841082
(decimal) = 41417724-EBA8953E
(hex)
You can check and test Hex conversation in the following site: http://babbage.cs.qc.edu/IEEE-754/ Copy 41417724EBA8953E
and paste in "Value to analyze" edit-box in above site and press enter.
But after transferring the two 32 bit integers I can not merge it to original 64 bit number. I tried to use the CDbl
and FormatNumber
functions in VBScript, but it fails!
Dim nL, nH, fL, fH, f64
nL = 1094809380 ' 4141 7724
nH = 3953694014 ' EBA8 953E
fL = CDbl($nL)
fH = CDbl($nH)
f64 = CDbl((fH * CDbl(2 ^ 32)) + CDbl(fL))
$strNum64 = FormatNumber( f64, 2)
So, how can I display a 64 bit number using VBScript on a 32 bit OS?
The "simple" answer to this, assuming pure VBScript, was to write a bignum add and multiply and then calculate the answer that way.
Using code from RosettaCode, I've created the following VeryLargeInteger class and a Hex64 function which says that 4702170486407730494 is the 64 bit decimal equivalent of 0x41417724EBA8953E
Option Explicit
Class VeryLongInteger
'http://rosettacode.org/wiki/Long_Multiplication#Liberty_BASIC
Public Function MULTIPLY(Str_A, Str_B)
Dim signA, signB, sResult, Str_Shift, i, d, Str_T
signA = 1
If Left(Str_A,1) = "-" Then
Str_A = Mid(Str_A,2)
signA = -1
End If
signB = 1
If Left(Str_B,1) = "-" Then
Str_B = Mid(Str_B,2)
signB = -1
End If
sResult = vbNullString
Str_T = vbNullString
Str_shift = vbNullString
For i = Len(Str_A) To 1 Step -1
d = CInt(Mid(Str_A,i,1))
Str_T = MULTBYDIGIT(Str_B, d)
sResult = ADD(sResult, Str_T & Str_shift)
Str_shift = Str_shift & "0"
'print d, Str_T, sResult
Next
If signA * signB < 0 Then sResult = "-" + sResult
'print sResult
MULTIPLY = sResult
End Function
Private Function MULTBYDIGIT(Str_A, d)
Dim sResult, carry, i, a, c
'multiply Str_A by digit d
sResult = vbNullString
carry = 0
For i = Len(Str_A) To 1 Step -1
a = CInt(Mid(Str_A,i,1))
c = a * d + carry
carry = c \ 10
c = c Mod 10
'print a, c
sResult = CStr(c) & sResult
Next
If carry > 0 Then sResult = CStr(carry) & sResult
'print sResult
MULTBYDIGIT = sResult
End Function
Public Function ADD(Str_A, Str_B)
Dim L, sResult, carry, i, a, b, c
'add Str_A + Str_B, for now only positive
l = MAX(Len(Str_A), Len(Str_B))
Str_A=PAD(Str_A,l)
Str_B=PAD(Str_B,l)
sResult = vbNullString 'result
carry = 0
For i = l To 1 Step -1
a = CInt(Mid(Str_A,i,1))
b = CInt(Mid(Str_B,i,1))
c = a + b + carry
carry = Int(c/10)
c = c Mod 10
'print a, b, c
sResult = CStr(c) & sResult
Next
If carry>0 Then sResult = CStr(carry) & sResult
'print sResult
ADD = sResult
End Function
Private Function Max(a,b)
If a > b Then
Max = a
Else
Max = b
End If
End Function
Private Function pad(a,n) 'pad from right with 0 to length n
Dim sResult
sResult = a
While Len(sResult) < n
sResult = "0" & sResult
Wend
pad = sResult
End Function
End Class
Function Hex64(sHex)
Dim VLI
Set VLI = New VeryLongInteger
Dim Sixteen(16)
Sixteen(0) = "1"
Sixteen(1) = "16"
Sixteen(2) = VLI.MULTIPLY(Sixteen(1),"16")
Sixteen(3) = VLI.MULTIPLY(Sixteen(2),"16")
Sixteen(4) = VLI.MULTIPLY(Sixteen(3),"16")
Sixteen(5) = VLI.MULTIPLY(Sixteen(4),"16")
Sixteen(6) = VLI.MULTIPLY(Sixteen(5),"16")
Sixteen(7) = VLI.MULTIPLY(Sixteen(6),"16")
Sixteen(8) = VLI.MULTIPLY(Sixteen(7),"16")
Sixteen(9) = VLI.MULTIPLY(Sixteen(8),"16")
Sixteen(10) = VLI.MULTIPLY(Sixteen(9),"16")
Sixteen(11) = VLI.MULTIPLY(Sixteen(10),"16")
Sixteen(12) = VLI.MULTIPLY(Sixteen(11),"16")
Sixteen(13) = VLI.MULTIPLY(Sixteen(12),"16")
Sixteen(14) = VLI.MULTIPLY(Sixteen(13),"16")
Sixteen(15) = VLI.MULTIPLY(Sixteen(14),"16")
Dim theAnswer, i, theDigit, theMultiplier, thePower, aPower
theAnswer = "0"
aPower = 0
For i = Len(sHex) To 1 Step -1
theDigit = UCase(Mid(sHex,i,1))
theMultiplier = InStr("0123456789ABCDEF",theDigit)-1
thePower = Sixteen(aPower)
thePower = VLI.MULTIPLY(CStr(theMultiplier),thePower)
theAnswer = VLI.ADD(theAnswer,thePower )
aPower = aPower + 1
Next
Hex64 = theAnswer
End Function
WScript.Echo Hex64("41417724EBA8953E")
I'd like to say "enjoy" but it's been more than six months since the original posting, so you've likely found another solution. All the same, it was fun.
LATER
The other way to do the Hex64, if you want to avoid the precalculation of the powers of 16 is:
Function Hex64b(sHex)
Dim VLI
Set VLI = New VeryLongInteger
Dim theAnswer, i, theDigit, theMultiplier, thePower, aPower
theAnswer = "0"
thePower = "1"
For i = Len(sHex) To 1 Step -1
theDigit = UCase(Mid(sHex,i,1))
theMultiplier = InStr("0123456789ABCDEF",theDigit)-1
theAnswer = VLI.ADD(theAnswer,VLI.MULTIPLY(thePower,theMultiplier))
thePower = VLI.MULTIPLY(thePower,"16")
Next
Hex64b = theAnswer
End Function
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With