Jeg snuble på dette SO spørgsmål , som bad om en måde for at konvertere større hexværdier til en positiv numerisk værdi:

?Val("&H8000") -32768 Val("&HFFFF") -1 

Mit svar involverede iterering af strengcifrene en efter en og beregning af deres respektive værdi i resultatet:

Function ConvertHex(ByVal value As String) As Double If Left(value, 2) = "&H" Then value = Right(value, Len(value) - 2) End If Dim result As Double Dim i As Integer, j As Integer For i = Len(value) To 1 Step -1 Dim digit As String digit = Mid$(value, i, 1) result = result + (16 ^ j) * Val("&H" & digit) j = j + 1 Next ConvertHex = result End Function 

Det virker, men jeg kan ” t hjælpe med at tænke, at jeg “har gjort noget dumt alt for kompliceret for noget, der skal være ret simpelt.

  • Jeg ' er forvirret over, hvad du vil opnå. " Dobbelt " betyder normalt et 64-bit flydende nummer. Alligevel siger din tekst, at du vil have en " positiv numerisk værdi ", men så ser dine eksempler ud til at vise signeret 16-bit heltal (kaldes normalt " kort "). Desuden ser det ud til, at kun hele tal muligvis kunne være repræsenteret i hex-strengen, så returtypen skal være Short, Integer, Long, UShort, UInteger, ULong eller Decimal.
  • @ 200_success Der ' er kun et meget begrænset sæt datatyper i VBA. Ingen usignerede typer …
  • Mat, hvad ' er forkert med Cdbl("&HFFFF")?
  • @Meehow se opdateringen af mit svar til, hvorfor jeg mener, at CDbl er forkert i dette scenarie.
  • @Meehow det er nøjagtigt hvad jeg mente med " Jeg ' har gjort noget dumt alt for kompliceret for noget, der skulle være ret simpelt " 😉

Svar

Fra hvad kan jeg fortælle en streng, der starter med &H er en bogstavelig bogstav.

Der findes et antal konverteringsfunktioner , der kan konvertere et udtryk til den ønskede type.

Så det skal simpelthen være, afhængigt af ønsket type:

Function ConvertHex(ByVal value As String) As Currency Dim result As Currency result = CCur(value) If result < 0 Then "Add two times Int32.MaxValue and another 2 for the overflow "Because the hex value is apparently parsed as a signed Int64/Int32 result = result + &H7FFFFFFF + &H7FFFFFFF + 2 End If ConvertHex = result End Function 

Valuta versus dobbelt

Maksimum nøjagtigt repræsentativ positiv heltal:

Så hvorfor bruge Currency over Double når sidstnævnte fungerer for et større udvalg af heltal?

Currency er altid nøjagtig. Hvis vi overløber en Currency -værdi, får vi en fejl. Hvis vi overløber den maksimale repræsentative heltalværdi af en dobbelt, får vi en omtrentlig heltalværdi:

Dim doubleMax As Double Dim doubleAfter As Double doubleMax = CDbl("&H0020000000000000") doubleAfter = doubleMax + 1 MsgBox "Double before: " & Format(doubleMax, "#") & vbNewLine & "after: " & Format(doubleAfter, "#") Dim currencyMax As Currency Dim currencyAfter As Currency currencyMax = CCur("&H000346DC5D638865") currencyAfter = currencyMax + 1 MsgBox "Currency before: " & Format(currencyMax, "#") & vbNewLine & "after: " & Format(currencyAfter, "#") 

Outputet af dette eksempel er:

 Double before: 9007199254740990 after: 9007199254740990  

Og så en run-time error "6": Overflow hvilket er fantastisk, hvis du ønsker at undgå afrundingsfejl. Nu hævder MSDN Double er

lagret som IEEE 64-bit (8-byte) floating-point-nummer

men hvis du har læst noget om IEEE 754 binary64 skal du være lidt overrasket over output fra eksemplet. Det faktiske maksimum er &H00038D7EA4C68000 (1.000.000.000.000.000).

Kommentarer

  • Awesome! Jeg ' har linket til dette svar på en redigering af mit SO-svar 🙂
  • Jeg udvidede lidt om Currency vs Double lidt og opdagede noget interessant.
  • hvad med doubleMax + doubleMax at kaste et overløbsfejl?
  • @Meehow Testede det bare og tilsyneladende overløber Double i VBA. Men det ' er stadig ikke muligt at løbe over, hvis det analyserede resultat er et heltal. Jeg ' er glad for, at jeg ikke ' behøver ikke at arbejde med dette sprog.
  • Den korrekte, idiomatiske måde at gøre dette på er at bruge en af de indbyggede konverteringsfunktioner, som @Meehow kommenterede OP – Jeg ved ikke ' hvad brainfart fik mig til selv at skrive denne funktion …

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *