Belebotlottam e SO kérdésbe, amely egy utat kérdezett nagyobb hexadecimális értékek pozitív számértékre konvertálása:
?Val("&H8000") -32768 Val("&HFFFF") -1
Válaszomban a karakterlánc számjegyeinek egyenkénti iterálását és a megfelelő érték kiszámítását eredményeztem:
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
Működik, de tudom ” Nem segít abban, hogy azt gondoljam, valami hülyén túl bonyolult dolgot tettem valamiért, aminek elég egyszerűnek kell lennie.
Van jobb módszer, nincs?
Megjegyzések
Válasz
Abból, amit meg tudok mondani egy karakterláncról, amelynek kezdete &H
egy hexa betűs szó.
Létezik egy számú konverziós függvény , amely képes átalakítani egy kifejezést a kívánt típusra.
Tehát egyszerűen annak kell lennie, a kívánt típustól függően:
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
Pénznem vs dupla
Maximálisan pontosan ábrázolható pozitív egész érték:
-
&H0020000000000000
(9,007,199,254,740,992) a Dupla ( IEEE 754 bináris64 ) -
&H000346DC5D638865
(922 337 203 685 477) a pénznemhez
Akkor miért használja a Currency
-t a Double
fölött, ha ez utóbbi az egész szám nagyobb tartományában működik?
Currency
mindig pontos. Ha túlcsordulunk egy Currency
értéket, hibát kapunk. Ha túllépjük a duplája maximálisan reprezentálható egész értékét, hozzávetőleges egész értéket kapunk:
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, "#")
A példa kimenete:
Double before: 9007199254740990 after: 9007199254740990
És akkor egy run-time error "6": Overflow
, ami nagyon jó, ha el akarják kerülni a kerekítési hibákat. Az MSDN azt állítja, hogy a Double
IEEE 64 bites (8 bájtos) lebegőpontos számként van tárolva
de ha valamit olvasott az IEEE 754 bináris64 fájlról, akkor kissé meglepődött a példa kimenetén. A tényleges maximum &H00038D7EA4C68000
(1 000 000 000 000 000).
Megjegyzések
- Félelmetes! Én ' összekapcsoltam ezt a választ egy SO válaszom szerkesztésénél 🙂
- kibővítettem a következőt:
Currency
vsDouble
egy kicsit, és valami érdekeset fedezett fel. - hogy
doubleMax + doubleMax
túlcsordulási hiba? - @ Valahogy csak teszteltem, és látszólag a VBA
Double
túlcsordul. De ' még mindig nem lehet túlcsordulni, ha az elemzett eredmény egész szám. I ' örülök, hogy nem ' nem kell dolgoznia az adott nyelvvel. - Ennek helyes, idiomatikus módja a beépített konverziós függvények egyikének használata, amint a @Meoud módon kommentálta az OP-t – Nem tudom, hogy ' nem tudom, mi okozott egy ötletet arra, hogy meg is írjam ezt a funkciót …
Short
,Integer
legyen,Long
,UShort
,UInteger
,ULong
, vagyDecimal
.Cdbl("&HFFFF")
? > @ Valahogy megnézem a válaszom frissítését, hogy miért gondolom, hogy aCDbl
nem megfelelő ebben a forgatókönyvben.