Damn, what a pain! A simple principle that should have taken me half an hour to implement took me about eight hours, partly because of data type precision issues and partly due to numerous fiddly bits and pieces.
Rem
HexToDec: Evaluate a hex string into a decimal number.
Untested but should work on non-Windows platforms.
Currently only evaluates whole numbers (ie non-fractional numbers).
Tested with BlitzMax V1.24
EndRem
SuperStrict
Graphics 800, 600
SeedRnd MilliSecs()
test
While Not KeyHit(KEY_ESCAPE)
If MouseHit(1) Or MouseHit(2)
test
EndIf
Wend
End
'********* TEST *************************************************
Function test()
Cls
DrawText "Click mouse button to generate some random values.", 10, 5
DrawText "(If the evaluation is correct then the result should equal the source.)", 10, 30
For Local n:Byte = 1 To 10
Local source:Long = Rand(0, 10000)
Local hexstr:String = Hex(source)
Local result:Long = HexToDec(hexstr)
DrawText "Source: " + source + ", Hex: " + hexstr + ", Result: " + result, 10, ((n + 2) * 30)
Next
Flip
EndFunction
'********** HexToDec FUNCTION *******************************************
'Simply cut and paste the hexToDec function into your program and use as required.
Function HexToDec:Long(s:String Var)
's - string to evalute. Non-hex characters will be ignored.
'returns a long integer
Global hex_chars:String[] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "a", "b", "c", "d", "e", "f"]
Local val:Double
'Strip non-hex characters
Local ts:String = ""
For Local i:Int = 0 To (s.length - 1)
Local ch:String = Chr(s[i])
Local found:Int = False
For Local i2:Int = 0 To hex_chars.length - 1
If ch = hex_chars[i2]
found = True
Exit
EndIf
Next
If found Then ts :+ ch
Next
'Remove leading zeros
Local count:Int = 0
For Local i:Int = 0 To (s.length - 1)
If Chr(ts[i]) <> "0" Then Exit Else count :+ 1
Next
ts = ts[count..s.length]
'Evaluate every character in the string
For Local i:Int = 0 To ts.length - 1
Local ch:String = Chr(ts[i])
Local chval:Byte
Select ch
Case "A", "a"
chval = 10
Case "B", "b"
chval = 11
Case "C", "c"
chval = 12
Case "D", "d"
chval = 13
Case "E", "e"
chval = 14
Case "F", "f"
chval = 15
Default
chval = ch.toInt()
EndSelect
val :+ (chval * (16 ^ (ts.length - 1.0 - i)))
Next
If (ts.length > 1) Then val :+ 1
'Overcome precision issues
Local remainder:Double = (val Mod 1)
If remainder = 0.0
If Long(val) > 15 Then Return Long(val - 1) Else Return Long(val)
Else
Return Long(val)
EndIf
EndFunction
|