Jag snubblade på den här SO-frågan som frågade om ett sätt för att konvertera större hex-värden till ett positivt numeriskt värde:

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

Mitt svar handlade om att itera strängsiffrorna en efter en och beräkna deras respektive värde till 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 fungerar, men jag kan ” t hjälp att tänka att jag ”har gjort något dumt för komplicerat för något som borde vara ganska enkelt.

Det finns ett bättre sätt, är det inte där?

Kommentarer

  • Jag ' är förvirrad över vad du vill åstadkomma. " Dubbel " betyder vanligtvis ett 64-bitars flytnummer. Ändå säger din text att du vill ha ett " positivt numeriskt värde ", men då verkar dina exempel visa signerad 16-bitars heltal (vanligtvis kallas " kort "). Dessutom verkar det som att endast heltal möjligen kan representeras i hexsträngen, så returtypen ska vara Short, Integer, Long, UShort, UInteger, ULong eller Decimal.
  • @ 200_success Det finns ' bara en mycket begränsad uppsättning datatyper i VBA. Inga osignerade typer …
  • Mat, vad ' är fel med Cdbl("&HFFFF")?
  • @Meehow se uppdateringen av mitt svar för varför jag tycker att CDbl är fel i det här scenariot.
  • @Meehow det är exakt vad jag menade med " Jag ' har gjort något dumt för komplicerat för något som borde vara ganska enkelt " 😉

Svar

Från vad jag kan säga en sträng som börjar med &H är en bokstavsordning.

Det finns ett antal konverteringsfunktioner som kan konvertera ett uttryck till önskad typ.

Så det borde helt enkelt vara, beroende på önskad typ:

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 kontra dubbel

Maximalt exakt representerbart positivt heltal:

Så varför använda Currency över Double när den senare fungerar för ett större antal heltal?

Currency är alltid korrekt. Om vi överskrider ett Currency -värde får vi ett fel. Om vi överskrider det maximalt representerbara heltalsvärdet för en dubbel får vi ett ungefärligt heltalvärde:

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, "#") 

Resultatet av detta exempel är:

 Double before: 9007199254740990 after: 9007199254740990  

Och sedan en run-time error "6": Overflow vilket är bra om du vill undvika avrundningsfel. Nu hävdar MSDN att Double är

lagrat som IEEE 64-bitars (8-byte) flytpunktsnummer

men om du har läst något om IEEE 754 binary64 borde du vara lite förvånad över resultatet från exemplet. Det faktiska maximumet är &H00038D7EA4C68000 (1.000.000.000.000.000).

Kommentarer

  • Fantastiskt! Jag ' har länkat till det här svaret på en redigering av mitt SO-svar 🙂
  • Jag utökade lite om Currency vs Double lite och upptäckte något intressant.
  • vad sägs om doubleMax + doubleMax att kasta en överflödesfel?
  • @Meehow Testade bara det och tydligen överflödar Double i VBA. Men det ' är fortfarande det går inte att överskrida om det analyserade resultatet är ett heltal. Jag ' är glad att jag inte ' t måste arbeta med det språket.
  • Det korrekta, idiomatiska sättet att göra detta är att använda en av de inbyggda konverteringsfunktionerna, som @Meehow kommenterade OP – Jag vet inte ' vad brainfart fick mig att ens skriva den här funktionen …

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *