Integer to IEEE Float

Monkey Forums/Monkey Code/Integer to IEEE Float

AdamRedwoods(Posted 2012) [#1]
Int to Float
IEEE Single Precision 32-bit

big endian
(doesn't handle NAN and INF)

This code is used to take Base64 integers and convert them back to float.

	Function IntToFloat:Float(b:Int)
		''big endian, ok if you read in entire int
		
		Local f_radix:Float[] = [0.00000011920928955078125, 0.0000002384185791015625, 0.000000476837158203125, 0.00000095367431640625,
						0.0000019073486328125, 0.000003814697265625, 0.00000762939453125, 0.0000152587890625, 0.000030517578125,
						0.00006103515625, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625,
						0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5]


		Local res:Float = 1.0
		
		Local s:Int = (b & $80000000)
		Local e:Int = ((b & $7f800000) Shr 23 ) -127 
		Local m:Int = b & $007fffff
		
		If m = 0 Then Return 0.0
		
		Local bit:Int = $00000001
		
		For Local i:Int=0 To 22
		
			If (bit Shl i) & m Then res += f_radix[i]			
			i += 1
			If (bit Shl (i)) & m Then res += f_radix[i]
			i += 1
			If (bit Shl (i)) & m Then res += f_radix[i]
			i += 1
			If (bit Shl (i)) & m Then res += f_radix[i]
			
		Next

		If e> 0 Then res = res * (2 Shl (e-1)) Elseif e<0 res = res / Float(2 Shl (-e-1) )
		'res = res * Pow(2,e)
		
		If s Then res = -res
		
		Return res
	End



Floyd(Posted 2012) [#2]
You don't need to handle all those bits separately. Do them in one fell swoop.

Function Int_To_Float:Float(b:Int)
		
		Local m:Int = b & $007fffff
		If m = 0 Then Return 0.0

		m += $00800000		
		Local s:Int = (b & $80000000)
		Local e:Int = ((b & $7f800000) Shr 23 ) - 150  ' 150=127+23
		Local res:Float = m * Pow( 2, e )

		If s Then res = -res
		Return res
		
	End


Note: We are both ignoring the special cases of NaN and Infinity. These have e=255, i.e. all bits = 1. Rather surprisingly I was able to write that code from memory. But I would have to look up the details to handle the e=255 cases properly.

This sure was easier when we had direct memory access. Here are versions for BlitzMax and Blitz3D et al. They could be used for testing Monkey results.

Function IntToFloat:Float( n:Int )
	Local fPtr:Float Ptr = Float Ptr Varptr( n )
	Return fPtr[0]
End Function


Function IntToFloat#( n )
	Local b = CreateBank( 4 )
	PokeInt b, 0, n
	Return PeekFloat( b, 0 )
End Function



AdamRedwoods(Posted 2012) [#3]
I thought there may be an easier way, many thanks!

As for direct memory access, Mark made a DataBuffers Class (hidden in opengl mod in Monkey v53) which allows just that with Peek and Poke.... and is the method I decided to go with for Base64 data loading.


Floyd(Posted 2012) [#4]
Mark made a DataBuffers Class (hidden in opengl mod in Monkey v53) which allows just that with Peek and Poke...

I had no idea that existed, but I haven't been keeping up with recent developments.