Integer to IEEE Float
Monkey Forums/Monkey Code/Integer to IEEE Float
| ||
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 |
| ||
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 |
| ||
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. |
| ||
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. |