kompastuin tähän SO-kysymykseen , joka kysyi tapaa muuntaa suuremmat heksadesimaaliarvot positiiviseksi numeeriseksi arvoksi:
?Val("&H8000") -32768 Val("&HFFFF") -1
Vastaukseni sisälsi merkkijonon numeroiden iteroinnin yksitellen ja niiden arvon laskemisen tulokseen:
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
Se toimii, mutta osaan ” Ei auta ajattelemassa, että olen tehnyt jotain typerästi liian monimutkaista jollekin, jonka pitäisi olla melko yksinkertaista.
Onko parempi tapa, etkö ole?
Kommentit
Vastaa
Mistä voin kertoa merkkijonon, joka alkaa &H
on kuusikulmion kirjain.
on useita muunnosfunktioita , jotka voivat muuntaa lausekkeen haluttuun tyyppiin.
Joten sen pitäisi yksinkertaisesti olla, riippuen halutusta tyypistä:
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
Valuutta vs. kaksinkertainen
Suurin tarkasti esitettävä positiivinen kokonaislukuarvo:
-
&H0020000000000000
(9,007,199,254,740,992) ryhmälle Kaksinkertainen ( IEEE 754 binary64 ) -
&H000346DC5D638865
(922 337 203 685 477) -valuutalle
Miksi siis käyttää Currency
yli Double
, kun jälkimmäinen toimii suuremmalla kokonaislukualueella?
Currency
on aina tarkka. Jos ylitämme Currency
-arvon, saat virheilmoituksen. Jos ylitämme kaksinkertaisen suurimman edustettavan kokonaisluvun arvon, saadaan likimääräinen kokonaislukuarvo:
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, "#")
Tämän esimerkin tulos on:
Double before: 9007199254740990 after: 9007199254740990
Ja sitten run-time error "6": Overflow
, joka on hieno, jos haluat välttää pyöristysvirheet. Nyt MSDN väittää, että Double
on
tallennettu IEEE 64-bittisenä (8-tavuisena) liukuluvunumerona
mutta jos olet lukenut jotain IEEE 754 -binaarisesta 64 , sinun pitäisi olla hieman yllättynyt esimerkin tuloksesta. Todellinen enimmäismäärä on &H00038D7EA4C68000
(1 000 000 000 000 000).
Kommentit
- Mahtavaa! Olen ' linkittänyt tämän vastauksen SO-vastaukseni muokkauksessa 🙂
- Laajensin bitin aiheesta
Currency
vsDouble
vähän ja löysi jotain mielenkiintoista. - Entä
doubleMax + doubleMax
heittää ylivuotovirhe? - @Meinäesti vain testasin sen ja ilmeisesti VBA: n
Double
ylivuoto. Mutta se ' on edelleen ei ole mahdollista ylivuotoa, jos jäsennetty tulos on kokonaisluku. I ' iloinen, että en ' ei tarvitse työskennellä kyseisen kielen kanssa. - Oikea, idiomaattinen tapa tehdä tämä on käyttää yhtä sisäänrakennetuista muunnosfunktioista, kuten @Me jotenkin kommentoi OP: ta – En tiedä ' en tiedä mikä aivoriihi sai minut jopa kirjoittamaan tämän toiminnon …
Short
,Integer
,Long
,UShort
,UInteger
,ULong
taiDecimal
.Cdbl("&HFFFF")
?CDbl
on mielestäni väärä tässä tilanteessa.