The fastest/quickest hex-to-dec and dec-to-hex

Before reading: The code presented is for the Monkey X multiplatform language. This was the fastest/quickest multiplatform solution I could design.

Okay, so there was a reason that I needed a blazing fast dec-to-hex and vice-versa
conversion. I’m not going to go over it. Anyways, after playing around for several hours I found a method that was fastest overall on all platforms.

The fastest method involved completely procedural type code. No looping for these conversions (it slowed it down in tests). I also tried to avoid any unnecessary string concatenation or calls that require looping through a string e.g. ToUpper and ToLower type functions.

Dec To Hex. I attempted to apply more “optimizations” to this one, but to no avail. This was the fastest way I could come up with. It can solve 10 million decimal to hex strings in 1 second on my machine. This was heavily optimized to take advantage of the Rope data structure that most web browsers and Flash use.

Function DecToHexBE:String( decimal:Int )
	Local a1:Int = decimal & 15
	Local a2:Int = (decimal Shr 4) & 15
	Local b1:Int = (decimal Shr 8) & 15
	Local b2:Int = (decimal Shr 12) & 15
	Local c1:Int = (decimal Shr 16) & 15
	Local c2:Int = (decimal Shr 20) & 15
	Local d1:Int = (decimal Shr 24) & 15
	Local d2:Int = (decimal Shr 28) & 15
 
	#If TARGET = "html5" Or TARGET = "flash"
	If a1 < 10 Then a1 = a1 + 48 Else a1 = a1 + 55
	If a2 < 10 Then a2 = a2 + 48 Else a2 = a2 + 55
	If b1 < 10 Then b1 = b1 + 48 Else b1 = b1 + 55
	If b2 < 10 Then b2 = b2 + 48 Else b2 = b2 + 55
	If c1 < 10 Then c1 = c1 + 48 Else c1 = c1 + 55
	If c2 < 10 Then c2 = c2 + 48 Else c2 = c2 + 55
	If d1 < 10 Then d1 = d1 + 48 Else d1 = d1 + 55
	If d2 < 10 Then d2 = d2 + 48 Else d2 = d2 + 55
 
	Return String.FromChar(d2) + String.FromChar(d1) + String.FromChar(c2) + String.FromChar(c1) +
		String.FromChar(b2) + String.FromChar(b1) + String.FromChar(a2) + String.FromChar(a1)
	#Else
	If a1 < 10 Then quickHex[7] = a1 + 48 Else quickHex[7] = a1 + 55
	If a2 < 10 Then quickHex[6] = a2 + 48 Else quickHex[6] = a2 + 55
	If b1 < 10 Then quickHex[5] = b1 + 48 Else quickHex[5] = b1 + 55
	If b2 < 10 Then quickHex[4] = b2 + 48 Else quickHex[4] = b2 + 55
	If c1 < 10 Then quickHex[3] = c1 + 48 Else quickHex[3] = c1 + 55
	If c2 < 10 Then quickHex[2] = c2 + 48 Else quickHex[2] = c2 + 55
	If d1 < 10 Then quickHex[1] = d1 + 48 Else quickHex[1] = d1 + 55
	If d2 < 10 Then quickHex[0] = d2 + 48 Else quickHex[0] = d2 + 55
 
	Return String.FromChars(quickHex)
	#EndIf
End
 
Function DecToHexLE:String( decimal:Int )
	Local a1:Int = decimal & 15
	Local a2:Int = (decimal Shr 4) & 15
	Local b1:Int = (decimal Shr 8) & 15
	Local b2:Int = (decimal Shr 12) & 15
	Local c1:Int = (decimal Shr 16) & 15
	Local c2:Int = (decimal Shr 20) & 15
	Local d1:Int = (decimal Shr 24) & 15
	Local d2:Int = (decimal Shr 28) & 15
 
	#If TARGET = "html5" Or TARGET = "flash"
	If a1 < 10 Then a1 = a1 + 48 Else a1 = a1 + 55
	If a2 < 10 Then a2 = a2 + 48 Else a2 = a2 + 55
	If b1 < 10 Then b1 = b1 + 48 Else b1 = b1 + 55
	If b2 < 10 Then b2 = b2 + 48 Else b2 = b2 + 55
	If c1 < 10 Then c1 = c1 + 48 Else c1 = c1 + 55
	If c2 < 10 Then c2 = c2 + 48 Else c2 = c2 + 55
	If d1 < 10 Then d1 = d1 + 48 Else d1 = d1 + 55
	If d2 < 10 Then d2 = d2 + 48 Else d2 = d2 + 55
 
	Return String.FromChar(a2) + String.FromChar(a1) + String.FromChar(b2) + String.FromChar(b1) +
		String.FromChar(c2) + String.FromChar(c1) + String.FromChar(d2) + String.FromChar(d1)
	#Else
	If a1 < 10 Then quickHex[1] = a1 + 48 Else quickHex[1] = a1 + 55
	If a2 < 10 Then quickHex[0] = a2 + 48 Else quickHex[0] = a2 + 55
	If b1 < 10 Then quickHex[3] = b1 + 48 Else quickHex[3] = b1 + 55
	If b2 < 10 Then quickHex[2] = b2 + 48 Else quickHex[2] = b2 + 55
	If c1 < 10 Then quickHex[5] = c1 + 48 Else quickHex[5] = c1 + 55
	If c2 < 10 Then quickHex[4] = c2 + 48 Else quickHex[4] = c2 + 55
	If d1 < 10 Then quickHex[7] = d1 + 48 Else quickHex[7] = d1 + 55
	If d2 < 10 Then quickHex[6] = d2 + 48 Else quickHex[6] = d2 + 55
 
	Return String.FromChars(quickHex)
	#EndIf
End
 
#If TARGET <> "html5" And TARGET <> "flash"
Global quickHex:Int[8]
#EndIf

Hex to Dec. This can solve 10 million hex to decimal conversions in about 1 second as well. This was surprising to me because hex to decimal has in the past always been slower for me. However, by avoiding any string manipulation I cut a lot of the workload down.

Function HexBEToDec:Int( hex:String )
	Local a1, a2, b1, b2, c1, c2, d1, d2, len, off
	len = hex.Length ' assuming 8 is the max without having to clamp
	off = 8 - len
 
	If len < 1 Then a1 = 0 Else a1 = hex[7 - off] - 48
	If len < 2 Then a2 = 0 Else a2 = hex[6 - off] - 48
	If len < 3 Then b1 = 0 Else b1 = hex[5 - off] - 48
	If len < 4 Then b2 = 0 Else b2 = hex[4 - off] - 48
	If len < 5 Then c1 = 0 Else c1 = hex[3 - off] - 48
	If len < 6 Then c2 = 0 Else c2 = hex[2 - off] - 48
	If len < 7 Then d1 = 0 Else d1 = hex[1 - off] - 48
	If len < 8 Then d2 = 0 Else d2 = hex[0] - 48
 
	If a1 > 9 Then a1 = a1 - 7 - (a1 / 48 * 32)
	If a2 > 9 Then a2 = a2 - 7 - (a2 / 48 * 32)
	If b1 > 9 Then b1 = b1 - 7 - (b1 / 48 * 32)
	If b2 > 9 Then b2 = b2 - 7 - (b2 / 48 * 32)
	If c1 > 9 Then c1 = c1 - 7 - (c1 / 48 * 32)
	If c2 > 9 Then c2 = c2 - 7 - (c2 / 48 * 32)
	If d1 > 9 Then d1 = d1 - 7 - (d1 / 48 * 32)
	If d2 > 9 Then d2 = d2 - 7 - (d2 / 48 * 32)
 
	Return a1 | (a2 Shl 4) | (b1 Shl 8) | (b2 Shl 12) | (c1 Shl 16) | (c2 Shl 20) | (d1 Shl 24) | (d2 Shl 28)
End
 
Function HexLEToDec:Int( hex:String )
	Local a1, a2, b1, b2, c1, c2, d1, d2, len
	len = hex.Length
 
	If len < 8 Then d1 = 0 Else d1 = hex[7] - 48
	If len < 7 Then d2 = 0 Else d2 = hex[6] - 48
	If len < 6 Then c1 = 0 Else c1 = hex[5] - 48
	If len < 5 Then c2 = 0 Else c2 = hex[4] - 48
	If len < 4 Then b1 = 0 Else b1 = hex[3] - 48
	If len < 3 Then b2 = 0 Else b2 = hex[2] - 48
	If len < 2 Then a1 = 0 Else a1 = hex[1] - 48
	If len < 1 Then a2 = 0 Else a2 = hex[0] - 48
 
	If a1 > 9 Then a1 = a1 - 7 - (a1 / 48 * 32)
	If a2 > 9 Then a2 = a2 - 7 - (a2 / 48 * 32)
	If b1 > 9 Then b1 = b1 - 7 - (b1 / 48 * 32)
	If b2 > 9 Then b2 = b2 - 7 - (b2 / 48 * 32)
	If c1 > 9 Then c1 = c1 - 7 - (c1 / 48 * 32)
	If c2 > 9 Then c2 = c2 - 7 - (c2 / 48 * 32)
	If d1 > 9 Then d1 = d1 - 7 - (d1 / 48 * 32)
	If d2 > 9 Then d2 = d2 - 7 - (d2 / 48 * 32)
 
	Return a1 | (a2 Shl 4) | (b1 Shl 8) | (b2 Shl 12) | (c1 Shl 16) | (c2 Shl 20) | (d1 Shl 24) | (d2 Shl 28)
End

With that last one you may be wondering, what is the (x / 48 * 32) calculation for. That calculation is to deal with lower case variables. It avoids the need to use ToUpper. See, because an integer calculation of anything below 48 will result in 0, which will subtract nothing. And any hex above that will result in 1. It’s actually possible to do the whole calculation in one swoop. However, because you would have to access the string it slows down the calculation quite a bit. So I just decided it would be better to solve it in two different groups.

 
 
© 2018 NRGsoft