2012-12-08 17 views
5

Ho un dispositivo che contiene parametri a 64 bit (Double). Posso leggere i suoi parametri Double usando il protocollo Modbus in due parti. Quindi ho diviso il numero a 64 bit in due numeri a 32 bit usando l'operazione bit a bit.Come posso visualizzare il doppio numero a 64 bit usando VBScript sul SO a 32 bit?

Esempio: 2289225.841082 (decimale) = 41417724-EBA8953E (hex)

È possibile controllare e la conversazione di prova Hex nel seguente sito: http://babbage.cs.qc.edu/IEEE-754/ Copia 41417724EBA8953E e incollare in "Valore per analizzare" edit-box nel sito di cui sopra e premere accedere.

Ma dopo aver trasferito i due numeri interi a 32 bit, posso non unirlo al numero di 64 bit originale. Ho provato a utilizzare le funzioni CDbl e FormatNumber in VBScript, ma non riesce!

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) 

Quindi, come è possibile visualizzare un numero a 64 bit utilizzando VBScript su un sistema operativo a 32 bit?

risposta

1

La "semplice" risposta a questo, presupponendo puro VBScript, era scrivere un bignum add e moltiplicare e quindi calcolare la risposta in questo modo.

Usando il codice da RosettaCode, ho creato la seguente classe VeryLargeInteger e una funzione Hex64 che dice che 4702170486407730494 è l'equivalente decimale a 64 bit di 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("ABCDEF",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") 

Mi piacerebbe dire "godere", ma sono passati più di sei mesi dalla pubblicazione originale, quindi probabilmente hai trovato un'altra soluzione. Comunque, è stato divertente.

DOPO

L'altro modo di fare la Hex64, se si vuole evitare il calcolo preventivo dei poteri del 16 è:

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("ABCDEF",theDigit)-1 
     theAnswer = VLI.ADD(theAnswer,VLI.MULTIPLY(thePower,theMultiplier)) 
     thePower = VLI.MULTIPLY(thePower,"16") 
    Next 
    Hex64b = theAnswer 
End Function 
Problemi correlati