Narazil jsem na tuto SO otázku , která se ptala na způsob převést větší hexadecimální hodnoty na kladnou číselnou hodnotu:

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

Moje odpověď zahrnovala iteraci číslic řetězce po jedné a výpočet jejich příslušné hodnoty do výsledku:

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 

Funguje to, ale můžu “ Nemohu si myslet, že jsem udělal něco hloupě přehnaně komplikovaného pro něco, co by mělo být docela jednoduché.

Existuje lepší způsob, není tam?

Komentáře

  • Jsem ' zmatený v tom, čeho chcete dosáhnout. " Dvojitý " obvykle znamená 64bitové číslo s plovoucí desetinnou čárkou. Váš text přesto říká, že chcete " kladnou číselnou hodnotu ", ale zdá se, že vaše příklady ukazují podepsané 16bitová celá čísla (obvykle se nazývají " krátká "). Dále se zdá, že v hexadecimálním řetězci mohou být zastoupena pouze celá čísla, takže návratový typ by měl být Short, Integer, Long, UShort, UInteger, ULong, nebo Decimal.
  • @ 200_success Existuje ' pouze velmi omezená sada datové typy ve VBA. Žádné nepodepsané typy …
  • Mat, co ' je špatně s Cdbl("&HFFFF")?
  • @Meehow viz aktualizace mé odpovědi, proč si myslím, že CDbl je pro tento scénář špatný.
  • @Meehow to je přesně co jsem myslel s " Udělal jsem ' něco hloupě přehnaně komplikovaného pro něco, co by mělo být docela jednoduché " 😉

Odpověď

Z toho, co mohu říct řetězci začínajícímu &H je hexadecimální literál.

Existuje počet konverzních funkcí , které mohou převést výraz na požadovaný typ.

Takže by to mělo být jednoduše, v závislosti na požadovaném typu:

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 

Měna vs. dvojnásobek

Maximum přesně reprezentovatelné kladné celé číslo:

Proč tedy používat Currency nad Double, když tato funkce funguje pro větší rozsah celých čísel?

Currency je vždy přesný. Pokud přetečeme Currency hodnotu, dostaneme chybu. Pokud přetečeme maximální reprezentovatelnou celočíselnou hodnotu dvojitého, dostaneme přibližnou celočíselnou hodnotu:

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

Výstup tohoto příkladu je:

 Double before: 9007199254740990 after: 9007199254740990  

A pak run-time error "6": Overflow což je skvělé, pokud se chcete vyhnout chybám zaokrouhlování. Nyní je tvrzení MSDN Double

uloženo jako 64bitové (8bajtové) číslo IEEE s plovoucí desetinnou čárkou

ale pokud jste si přečetli něco o IEEE 754 binary64 , měli byste být trochu překvapen výstupem z příkladu. Skutečné maximum je &H00038D7EA4C68000 (1 000 000 000 000 000).

Komentáře

  • Úžasné! S touto odpovědí jsem ' propojil úpravu své SO odpovědi 🙂
  • Rozšířil jsem část o Currency vs Double trochu a objevil něco zajímavého.
  • co tak doubleMax + doubleMax hodit chyba přetečení?
  • @Meehow Právě jste to otestovali a zjevně Double ve VBA přeteče. Ale ' stále není možné přetečení, pokud je analyzovaným výsledkem celé číslo. Jsem ' rád, že ned ' s tímto jazykem pracovat nemusíme.
  • Správným idiomatickým způsobem je použití jedné z integrovaných funkcí převodu, jak @Meehow komentoval OP – Nevím ' nevím, co mi brainfart způsobil, že jsem tuto funkci dokonce napsal …

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *