Mi sono imbattuto in questa domanda SO che chiedeva un modo per convertire valori esadecimali più grandi in un valore numerico positivo:

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

La mia risposta prevedeva literazione delle cifre della stringa una per una e il calcolo del rispettivo valore nel risultato:

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 

Funziona, ma posso ” Non aiuta a pensare di aver fatto qualcosa di stupidamente troppo complicato per qualcosa che dovrebbe essere piuttosto semplice.

Esiste un modo migliore, no?

Commenti

  • Sono ' confuso su ciò che vuoi ottenere. " Doppio " di solito indica un numero a virgola mobile a 64 bit. Tuttavia, il tuo testo dice che vuoi un " valore numerico positivo ", ma i tuoi esempi sembrano mostrare firmato Numeri interi a 16 bit (solitamente chiamati " short "). Inoltre, sembrerebbe che nella stringa esadecimale possano essere rappresentati solo numeri interi, quindi il tipo restituito dovrebbe essere Short, Integer, Long, UShort, UInteger, ULong o Decimal.
  • @ 200_success Cè ' solo un insieme molto limitato di tipi di dati in VBA. Nessun tipo senza segno …
  • Mat, cosa ' non va con Cdbl("&HFFFF")?
  • @Meehow vede laggiornamento alla mia risposta per il motivo per cui penso che CDbl sia sbagliato per questo scenario.
  • @Meehow che è esattamente cosa intendevo con " ' ho fatto qualcosa di stupidamente eccessivamente complicato per qualcosa che dovrebbe essere piuttosto semplice " 😉

Risposta

Da quello che posso dire una stringa che inizia con &H è un letterale esadecimale.

Esiste un numero di funzioni di conversione che possono convertire unespressione al tipo desiderato.

Quindi dovrebbe essere semplicemente, a seconda del tipo desiderato:

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 vs doppia

Valore intero positivo massimo rappresentabile con precisione:

Allora perché utilizzare Currency su Double quando questultimo funziona per un intervallo più ampio di numeri interi?

Currency è sempre accurato. Se eccediamo un valore Currency otteniamo un errore. Se superiamo il valore intero massimo rappresentabile di un double, otteniamo un valore intero approssimativo:

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

Loutput di questo esempio è:

 Double before: 9007199254740990 after: 9007199254740990  

E poi un run-time error "6": Overflow che è fantastico se tu desidera evitare errori di arrotondamento. Ora MSDN afferma che Double è

memorizzato come numero a virgola mobile IEEE a 64 bit (8 byte)

ma se “hai letto qualcosa sul IEEE 754 binary64 dovresti essere un po sorpreso dalloutput dellesempio. Il massimo effettivo è &H00038D7EA4C68000 (1,000,000,000,000,000).

Commenti

  • Fantastico! Ho ' collegato a questa risposta in una modifica alla mia risposta SO 🙂
  • Ho ampliato la parte su Currency vs Double un po e ho scoperto qualcosa di interessante.
  • che ne dici di doubleMax + doubleMax lanciare un errore di overflow?
  • @Meehow Lho appena testato e apparentemente Double in VBA va in overflow. Ma ' è ancora non è possibile eseguire loverflow se il risultato analizzato è un numero intero. ' sono contento di averlo fatto ' t deve lavorare con quella lingua.
  • Il modo corretto e idiomatico per farlo è usare una delle funzioni di conversione integrate, come ha commentato @Meehow sullOP – Non ' non so cosa brainfart mi abbia fatto scrivere questa funzione …

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *