Converting Between Single Precision and Double Precision Floats In Basic
The Armmites and Picomites use double precision floats. When interfacing some devices they will return the 32 bits that represent a single precision float. In the Micromites which use single precision you can just POKE the 32 bits into the memory occupied by a float and then access the value by using the variable.
The MMBasic devices using double precision expect you to POKE 64 bits, but you only have 32. See this post for how to manipulate the bits so you end up with 64 bits in the format expected by double precision.
Allocation of the 32 bits of a single precision float Allocation of the 64 bits of a double precision float
Functions in MMBasic
Function to convert from single to double precision
These functions manipulate the bits in a stored float to go between single and double precision float as required. They are contributed by various TBS members and are extracted from the TBS thread.
'================================================================================================ ' Configure platform specific variables '================================================================================================ DIM integer doubleprecision if (MM.DEVICE$="Micromite MkII" OR MM.DEVICE$="Micromite Plus") THEN doubleprecision=0 else doubleprecision=1 ENDIF '--------------------------------------------------------------------------------- 'This function takes a float (single or double precision depending on the platform) 'and returns an integer where the last 32 bits contain binary formatted as for a '32 bit float.(This could then be sent to a device that expects single precision). '--------------------------------------------------------------------------------- Function FloatToBIN32(i As FLOAT) As INTEGER local INTEGER w%,c%,d%,e%,o% Local INTEGER j if doubleprecision=0 then FloatToBIN32=Peek(INTEGER Peek(VARADDR i)) else Poke FLOAT Peek(varaddr w%),i 'store the 64 bits double precision HEX of the floating point to w% c%=(w% And &H8000000000000000)>>32 'get the sign bit back to Bit32 d%=(w% And &hFFFFFE0000000)>>29 'get the shortened mantissa and move to new position e%=(((w% And &H7FF0000000000000)>>52)+127-1023)<<23 'get the exponent and convert o%=(c% Or d% Or e%) Poke integer Peek(varaddr j),o% 'put the answer into the integer FloatToBIN32=j endif End Function '--------------------------------------------------------------------------------- 'This function takes an integer where the last 32 bits contain binary formatted as 'for a 32 bit float.(This could be from a device works in single precision). 'It returns a float (single or double precision to match the current platform) '--------------------------------------------------------------------------------- Function BIN32ToFloat(i As INTEGER) As FLOAT Local float j local INTEGER w%,c%,d%,e%,o% if doubleprecision=0 then Poke INTEGER Peek(VARADDR j),i BIN32ToFloat=j else Poke word Peek(varaddr w%),i 'store the single precision HEX of the floating point c%=(w% And &H80000000)<<32 'get the sign bit d%=(w% And &h7FFFFF)<<29 'get the mantissa e%=(((w% And &H7f800000)>>23)-127+1023)<<52 'get the exponent and convert o%=(c% Or d% Or e%) Poke integer Peek(varaddr j),o% 'put the answer into a double BIN32ToFloat=j ENDIF End Function
Function to convert from single to double precision
A variation of the functions that accept the input as a string.
'you pass in the 4 hex bytes of the single-precision number as a string 'The function returns the double precision float function CDBL(s$) local w%,c%,d%,e%,o%,a! If Left$(s$,2)<>"&H" Then s$="&H"+s$ Poke word Peek(varaddr w%),Val(s$) 'store the single precision floating point c%=(w% And &H80000000)<<32 'get the sign bit d%=(w% And &h7FFFFF)<<29 'get the mantissa e%=(((w% And &H7f800000)>>23)-127+1023)<<52 'get the exponent and convert o%=(c% Or d% Or e%) Poke integer Peek(varaddr a!),o% 'put the answer into a double CDBL=a! end function
Function to convert from double to single precision
Use this to manipulate a double precision float to extract 32 bits formatted as single precision needed to send data to a device that expects only 32bits.
'you pass in the 8 byte double-precision float number 'The function returns a hex string containing the 32bits for the single precision float. Function CSGL$(a!) Local out$="", sgl$="" sgl$= Bin2str$(single, a!, BIG) For n=1 To 4 out$=out$+Hex$(Str2bin(uint8,Mid$(sgl$,n,1)),2) Next CSGL$ = out$ End Function