(see also Convert Microsoft/IEEE Float binary into a string in Classic REXX; especially the addendum)
/**********************************************************************/
/* These routines are the original work of Thos Davis */
/* (see EMail Addresses) */
/* and to the best of his knowledge do not include any copyrighted */
/* materials. */
/* */
/* These routines are hereby released into the Public Domain */
/**********************************************************************/
/* Microsoft/IEEE Float binary: *
+--------------------------------------------------------------------+
|bit |0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F|
+====+=============================================+=+===============+
|MKS | mantissa |s| exponent |
+----+---------------------------------------------+-+-------------+-|
|IEEE| mantissa | exponent |s|
+--------------------------------------------------+---------------+-+
*/
/* In both cases, the mantissa is the lower (least significant) */
/* 23 bits (plus an implied value of 1 for bit 24, the most */
/* significant bit of the mantissa), the sign is one bit, and */
/* the exponent is 8 bits. */
/* */
/* Because the mantissa has a 'virtual bit' whose value is always 1, */
/* the exponent is used to determine if the value is 0. */
/* */
/* IEEE Double Float binary is the same format as the single Float */
/* but the mantissa is 52 bits long (for 53 bits of significant */
/* binary digits [is that bigits?] after including the 'virtual 1' */
/* most significant bit) and the exponent is 11 bits long. */
/* */
/* !!! I M P O R T A N T !!! */
/* */
/* NUMERIC DIGITS should be set to about 16 to get the full value of */
/* Doubles */
/* */
/* !!! A L S O I M P O R T A N T !!! */
/* */
/* These functions may not correctly recognize the special values */
/* +INF plus infinity */
/* -INF minus infinity */
/* +NAN not a number */
/* -NAN not a number */
/* */
::ROUTINE mksToString PUBLIC
use arg TheFloat
/* mks is the format used in older versions of */
/* MicroSoft BASIC and is, for some bizarre */
/* reason, used as the index value in the QWK */
/* BBS message packing scheme */
if TheFloat~Length \= 4 then
return 'NOT-A-FLOAT'
bFloat = TheFloat~Reverse~c2x~x2b~Right(32,'0')
fMantissa = '1' || bFloat~Right(23)
fExponent = bFloat~Left( 8 )
fSign = bFloat~SubStr( 9, 1 )
magicNumber = 152
return GeneralFloat( fSign, fMantissa, fExponent, magicNumber, Digits() )
::ROUTINE FloatToString PUBLIC
use arg TheFloat
if TheFloat~Length \= 4 then
return 'NOT-A-FLOAT'
bFloat = TheFloat~Reverse~c2x~x2b~Right(32,'0')
fMantissa = '1' || bFloat~Right(23)
fExponent = bFloat~SubStr( 2, 8 )
fSign = bFloat~Left(1)
magicNumber = 150
/* IS SPECIAL VALUE */
if fExponent = '11111111' then
return SpecialFloat( fSign, fMantissa, 'S' )
else
return GeneralFloat( fSign, fMantissa, fExponent, magicNumber, Digits() )
::ROUTINE DoubleToString PUBLIC
use arg TheDouble
NUMERIC DIGITS 16
if TheFloat~Length \= 8 then
return 'NOT-A-FLOAT'
bDouble = TheDouble~Reverse~c2x~x2b~Right(64,'0')
dMantissa = '1' || bDouble~Right(52)
dExponent = bDouble~SubStr( 2, 11 )
dSign = bDouble~Left(1)
magicNumber = 1075
/* IS SPECIAL VALUE */
if dExponent = '11111111111' then
return SpecialFloat( dSign, dMantissa, 'D' )
else
return GeneralFloat( dSign, dMantissa, dExponent, magicNumber, Digits() )
::ROUTINE GeneralFloat
use arg theSign, theMantissa, theExponent, magicNumber, numdigits
NUMERIC DIGITS numdigits
if theExponent = 0 then
ascFloat = 0
else
ascFloat = (theMantissa~b2x~x2d) * ( 2 ** ( (theExponent~b2x~x2d) - magicNumber ))
if theSign then
ascFloat = '-'ascFloat
return ascFloat
::ROUTINE SpecialFloat
use arg theSign, theMantissa, theType
SELECT
WHEN theType = 'S' then lenMantissa = 24
WHEN theType = 'D' then lenMantissa = 53
END
SELECT
WHEN theMantissa = '1'~Left( lenMantissa, '0' ) THEN
ieeeSpecial = 'INFINITY'
WHEN theMantissa = '11'~Left( lenMantissa, '0' ) THEN
ieeeSpecial = 'NOT-A-NUMBER'
OTHERWISE
ieeeSpecial = 'UNKNOWN-MEANING'
END /* SELECT */
if theSign then
ieeeSpecial = '-'ieeeSpecial
else
ieeeSpecial = '+'ieeeSpecial
return 'IEEE:' ieeeSpecial