mmbasic:converting_a_single_precision_float_to_double_in_basic

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.

This TBS post

Allocation of the 32 bits of a single precision float single Allocation of the 64 bits of a double precision float double

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
mmbasic/converting_a_single_precision_float_to_double_in_basic.txt · Last modified: 2024/07/30 16:20 by gerry