M-am împiedicat de această întrebare SO care întreba despre un mod pentru a converti valori hexagonale mai mari într-o valoare numerică pozitivă:

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

Răspunsul meu a presupus iterarea cifrelor șirului una câte una și calcularea valorii respective în rezultat:

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 

Funcționează, dar pot ” Nu mă gândesc că am făcut ceva stupid prea complicat pentru ceva care ar trebui să fie destul de simplu.

Există o modalitate mai bună, nu există?

Comentarii

  • Sunt ' confuz cu privire la ceea ce doriți să realizați. " Dublu " înseamnă de obicei un număr în virgulă mobilă pe 64 de biți. Cu toate acestea, textul dvs. spune că doriți o " valoare numerică pozitivă ", dar apoi exemplele dvs. par să arate semnat Numere întregi de 16 biți (denumite de obicei " scurt "). În plus, s-ar părea că numai numerele întregi ar putea fi reprezentate în șirul hexagonal, deci tipul de returnare ar trebui să fie Short, Integer, Long, UShort, UInteger, ULong, sau Decimal.
  • @ 200_success Există ' doar un set foarte limitat de tipuri de date în VBA. Fără tipuri nesemnate …
  • Mat, ce ' e greșit cu Cdbl("&HFFFF")?
  • @Meehow vezi actualizarea răspunsului meu de ce cred că CDbl este greșit pentru acest scenariu.
  • @Meehow asta este exact ce am vrut să spun cu " Am ' am făcut ceva stupid prea complicat pentru ceva care ar trebui să fie destul de simplu " 😉

Răspuns

Din ceea ce pot spune un șir care începe cu &H este un literal hexagonal.

Există un număr număr de funcții de conversie care poate converti o expresie la tipul dorit.

Deci ar trebui să fie pur și simplu, în funcție de tipul dorit:

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 

Monedă vs Dublu

Valoarea maximă a numărului întreg pozitiv reprezentabil cu precizie:

Deci, de ce să folosiți Currency peste Double atunci când acesta din urmă funcționează pentru o gamă mai mare de numere întregi?

este întotdeauna corect. Dacă depășim o valoare Currency vom obține o eroare. Dacă depășim valoarea maximă întreagă reprezentabilă a unui dublu, obținem o valoare întreagă aproximativă:

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

Rezultatul acestui exemplu este:

 Double before: 9007199254740990 after: 9007199254740990  

Și apoi un run-time error "6": Overflow care este minunat dacă doriți să evitați erorile de rotunjire. Acum, revendicările MSDN Double este

stocat ca număr cu virgulă mobilă IEEE pe 64 de biți (8 octeți)

dar dacă ați citit ceva despre IEEE 754 binary64 ar trebui să fiți un pic surprins de rezultatul din exemplu. Maximul real este &H00038D7EA4C68000 (1.000.000.000.000.000).

Comentarii

  • Minunat! Am ' legat de acest răspuns într-o editare la răspunsul meu SO 🙂
  • Am extins bitul despre Currency vs Double puțin și am descoperit ceva interesant.
  • ce zici de doubleMax + doubleMax aruncând un eroare de revărsare?
  • @Meehow Tocmai a testat-o și aparent Double în VBA se revarsă. Dar ' este încă nu este posibil să depășesc dacă rezultatul analizat este un număr întreg. Mă ' mă bucur că nu nu trebuie să funcționeze cu acest limbaj.
  • Modul corect, idiomatic de a face acest lucru este să folosiți una dintre funcțiile de conversie încorporate, așa cum a comentat @Meehow despre OP – Nu ' nu știu ce brainfart m-a determinat să scriu chiar această funcție …

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *