środa, 11 maja 2016

• Test funkcji HexToDec

W poprzednim artykule HexToDec pisałem o problemach konwersji z zapisu postaci heksadecymalnej na postać dziesiętną przy użyciu funkcji Val(ciąg). Aby ustrzec się błędów podczas konwersji z postaci heksadecymalnej na postać dziesiętną powinniśmy pilnować typów liczb, jakie powinna zwrócić funkcja konwertująca, poprzez stosowanie znaków deklaracji typu liczby (sufiksów %&^. Zaproponowałem, by zamiast używać funkcji Val(ciąg) i sufiksów typu liczby (%&^) w funkcjach konwertujących, używać funkcji konwersji typu według poniższego schematu:


Debug.Print "CByte", CByte("&H" & sHex)
Debug.Print "CInt", CInt("&H" & sHex)
Debug.Print "CLng", CLng("&H" & sHex)
Debug.Print "CSng", CSng("&H" & sHex)
Debug.Print "CDbl", CDbl("&H" & sHex)
Debug.Print "CDec", CDec("&H" & sHex)
Debug.Print "CCur", CCur("&H" & sHex)
#If VBA7 Then
   Debug.Print "CLngLng", CLngLng("&H" & sHex)
   Debug.Print "CLngPtr", CLngPtr("&H" & sHex)
#End If
Public Function HexToDec(ByVal sHex As String)

 Debug.Print "CByte", CByte("&H" & sHex)
  Debug.Print "CInt", CInt("&H" & sHex)
  Debug.Print "CLng", CLng("&H" & sHex)
  Debug.Print "CSng", CSng("&H" & sHex)
  Debug.Print "CDbl", CDbl("&H" & sHex)
  Debug.Print "CDec", CDec("&H" & sHex)
  Debug.Print "CCur", CCur("&H" & sHex)
  #If VBA7 Then
    Debug.Print "CLngLng", CLngLng("&H" & sHex)
    Debug.Print "CLngPtr", CLngPtr("&H" & sHex)
  #End If

End Function

Na podstawie powyższego schematu, napisałem funkcją testującą konwersję z zapisu postaci heksadecymalnej na postać dziesiętną:


Public Function testHexToDec(ByVal sHex As String)
On Error GoTo ErrHandler
Const errOVERFLOW = 6
Const errMISMATCH = 13

 Debug.Print "CByte", CByte("&H" & sHex)
  Debug.Print "CInt", CInt("&H" & sHex)
  Debug.Print "CLng", CLng("&H" & sHex)
  Debug.Print "CSng", CSng("&H" & sHex)
  Debug.Print "CDbl", CDbl("&H" & sHex)
  Debug.Print "CDec", CDec("&H" & sHex)
  Debug.Print "CCur", CCur("&H" & sHex)
  #If VBA7 Then
    Debug.Print "CLngLng", CLngLng("&H" & sHex)
    Debug.Print "CLngPtr", CLngPtr("&H" & sHex)
  #End If

ExiHere:
  Exit Function
ErrHandler:
  If Err.Number = errOVERFLOW Or Err.Number = errMISMATCH Then
    Debug.Print "Błąd nr " & Err.Number & "  " & Err.Description
    Resume Next
  Else
    MsgBox "Błąd nr " & Err.Number & vbNewLine & Err.Description
    Resume ExiHere
  End If
End Function 
 

Poniżej wyniki przykładowych wywołań funkcji konwersji typu:
&HFFFF,
&HFFFF FFFF,
&HFFFF FFFF FFFF,
&HFFFF FFFF FFFF FFFF,
&H8000,
&H8000 0000,
&H8000 0000 0000,
&H8000 0000 0000 0000 0000,
oraz test konwersji dolnej i górnej granicy zakresu liczbu typu Long
Hex$(-2 147 483 648) i Hex$(2 147 483 647)

Test w 64-bitowym środowisku VBA7 na konwersję do postaci heksadecymalnej i potem powrotną konwersję na postać dziesiętną, liczby 2 147 483 647 będącej górnym zakresem liczby typu Long

' górna granica zakresu Long = 2 147 483 647
   Hex$(2147483647) = 7FFFFFFF
   CLng("&H" & "7FFFFFFF") = 2147483647
' w wersji skróconej test ma postać:
   CLng("&H" & Hex$(2147483647)) = 2147483647
' i równość ta jest prawdziwa

oraz liczby -2 147 483 648 będącej dolną granicą zakresu liczby typu Long

' dolna granica zakresu Long = -2 147 483 648
   Hex$(-2147483648) = FFFFFFFF80000000
   CLng("&H" & "FFFFFFFF80000000") = Błąd nr 13. Type mismatch
' wynik nieznany, gdyż MS Access wyświetla komunikat:
' MS Access podczas konwersji na postać heksadecymalną potraktował liczbę -2147483648 jako typ LongLong i aby otrzymać prawidłową wartość, musimy przekonwertowanej liczbę z postaci heksadecymalnej na typ LonLong
   CLngLng("&H" & "FFFFFFFF80000000") = -2147483648

Wcześniej pisałem, by ustrzec się błędów podczas konwersji z postaci heksadecymalnej na postać dziesiętną powinniśmy pilnować typów liczb, jakie powinna zwrócić funkcja konwertująca. Jak widać, powinniśmy pilnować także typu liczby poddawanej konwersji na postać heksadecymalną.

' dolna granica zakresu Long = -2 147 483 646
   Hex$(CLng(-2147483648)) = 80000000
   CLng("&H" & "80000000") = -2147483648
' w wersji skróconej test ma postać:
   CLng("&H" & Hex$(CLng(-2147483648))) = -2147483648
' i równość ta jest prawdziwa