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.
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:
-
&H0020000000000000
(9,007,199,254,740,992) for Dobbelt ( IEEE 754 binary64 ) -
&H000346DC5D638865
(922,337,203,685,477) til Valuta
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
vsDouble
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 …
Short
,Integer
,Long
,UShort
,UInteger
,ULong
ellerDecimal
.Cdbl("&HFFFF")
?CDbl
er forkert i dette scenarie.