Page 1 of 1

Displaying binary representations of Floats

Posted: Sun May 28, 2006 3:44 pm
by Kale
Code updated for 5.20+

I've been playing around with floating point numbers and trying to understand how they are stored using binary. I think i've got a pretty good handle on it now and come up with this code. It allows you to input a number in the 'DecimalNumber.s' var to examine, then display usefull info in the Debug Output window.

Code: Select all

;For all 32 bit floating point numbers encoded in the IEEE 754 standard,
;the bits are arranged like this:
;
;Sign bit   Exponent   Significand (Mantissa)
;0          00000000   00000000000000000000000
;
;31         30----23   22-----bit index------0
;
;1 bit for the sign, 8 bits for the exponent and 23 bits for the significand.
;

;]=============================================================================
;-CONSTANTS
;[=============================================================================

#SIZE_OF_SIGN = 1 ;bit
#SIZE_OF_EXPONENT = 8 ;bits
#SIZE_OF_SIGNIFICAND = 23 ;bits
#EXPONENT_BIAS = 127

;]=============================================================================
;-PROCEDURES
;[=============================================================================

Procedure.q ValB(String.s)
   Protected Result.q
   Protected Pointer.l = @String
   For x.l = 1 To Len(String)
      Result = (Result << 1) + PeekC(Pointer) - 48
      Pointer + SizeOf(Character)
   Next x
   ProcedureReturn Result
EndProcedure

;]=============================================================================
;-MAIN
;[=============================================================================

;Type a decimal floating point number here to examine:
DecimalNumber.s = "0.1"

;Examinations:
FloatingPointNumber.f = ValF(DecimalNumber)
BinaryString.s = RSet(Bin(PeekL(@FloatingPointNumber)), 32, "0")
SignBitString.s = Mid(BinaryString, 1, #SIZE_OF_SIGN)
ExponentString.s = Mid(BinaryString, 1 + #SIZE_OF_SIGN, #SIZE_OF_EXPONENT)
SignificandString.s = Mid(BinaryString, 1 + #SIZE_OF_SIGN + #SIZE_OF_EXPONENT, #SIZE_OF_SIGNIFICAND)

Debug "Original Decimal Floating Point Number: "
Debug DecimalNumber
Debug ""
Debug "-----------------------------------------------------------------------"
Debug "Internal Binary Representation:"
Debug StrF(FloatingPointNumber, 18) + "  -  (" + BinaryString + ")"
Debug ""
Debug "Sign bit: " + SignBitString
Debug "Exponent: " + ExponentString + "  (" + Str(ValB(ExponentString) - #EXPONENT_BIAS) + ")"
Debug "Significand: " + "(1.)" + SignificandString
Debug "-----------------------------------------------------------------------"
Debug ""

;Read the floating point number from its binary source:

Exponent.q = ValB(ExponentString) - #EXPONENT_BIAS
If Exponent < 0
   SignificandString = RSet("1" + SignificandString, #SIZE_OF_SIGNIFICAND + -Exponent, "0")
   IntegerPart.q = 0
   FractionalPart.q = ValB(SignificandString)
Else
   IntegerPart.q = ValB("1" + Mid(SignificandString, 1, Exponent))
   FractionalPart.q = ValB(Mid(SignificandString, Exponent + 1, #SIZE_OF_SIGNIFICAND - Exponent))
EndIf

;Display the floating point number read from binary:
Debug "The floating point number re-read from binary is:"
If SignBitString = "1"
   Debug "-" + StrF(IntegerPart + FractionalPart / Pow(2, #SIZE_OF_SIGNIFICAND - Exponent), 18)
Else
   Debug StrF(IntegerPart + FractionalPart / Pow(2, #SIZE_OF_SIGNIFICAND - Exponent), 18)
EndIf
Debug ""
Debug ""
I'm pretty sure this code can handle any number to be stored in a float but i keep reading things about 'Denormal Numbers'! I can't seem to find a source which can explain these to me other than stuff that looks like a rocket science manual. So if any one can fill me in to what they are i would be grateful. ;)

Posted: Sun May 28, 2006 4:23 pm
by Trond
That's what I call doing it the hard way. :wink:

Code: Select all

Float.f = 0.1
Long.l = PeekL(@Float)

Debug "Original number:"
Debug Float
Debug "Internal binary representation:"
Debug RSet(Bin(Long), 8*4, "0")
Debug "Float, re-read from binary:"
Float = 0
Float = PeekF(@Long)
Debug Float

Posted: Sun May 28, 2006 6:36 pm
by Kale
Trond wrote:That's what I call doing it the hard way. :wink:

Code: Select all

Float.f = 0.1
Long.l = PeekL(@Float)

Debug "Original number:"
Debug Float
Debug "Internal binary representation:"
Debug RSet(Bin(Long), 8*4, "0")
Debug "Float, re-read from binary:"
Float = 0
Float = PeekF(@Long)
Debug Float
Yes your code is a little bit shorter but it doesn't do what mine does, ;) and that is read and decode 32 bit binary to extrapolate the floating point number contained within. In mine i read the sign, the exponent and the significand and process these in order to give me the stored float.

I've done it this way to show how it is done while i was learning how to do it. :)

Posted: Sun May 28, 2006 7:03 pm
by dioxin
Kale,
Normalised 32 bit FP numbers are of this format:

Code: Select all

sEEEEEEEEfffffffffffffffffffffff   s=sign, E=exponent (biased by adding 127), f=fractional part and there is an implied 1 ahead of the fractional part so the mantissa actually has 24 bits, not the 23 you may expect. i.e. the number is really:

<S> 1.fffffffffffffffffffffff x 2^(EEEEEEEE - 127)

	The Exponent range for normalised numbers is -126 to +127 (EEEEEEEE= 1 to 254)
	If EEEEEEEE = 255 then the number is infinite or Not A Number.
	If EEEEEEEE = 0   then the number is either zero or denormalised.
 
Denormalized numbers are the range of numbers which are too small to be represented in the normalised format because the exponent can't go below 1, but which can still be usefully represented in the bits available, although at lower precision.

You can recognise a denormalised number from EEEEEEEE.
If the EEEEEEEE is zero AND ff..ff is zero then the number represented is zero
If the EEEEEEEE is zero AND ff..ff is non-zero then the number represented is denormalised.
The denormalised number has an implied leading 0 rather than the implied leading 1 of normalised numbers.
The exponent of the denormalised number is always -126 as the smaller size of smaller numbers is taken into account by shifting the bits right in the mantissa rather than by decrementing the exponent further.

The smallest number that can be held normalised is:

Code: Select all

sEEEEEEEEfffffffffffffffffffffff
s0000000100000000000000000000000
which represents <s>1.0 x 2^-126

If we decrease the number by 1 count in the LSB we get:

Code: Select all

sEEEEEEEEfffffffffffffffffffffff
s0000000011111111111111111111111
which is the biggest denormalised number.
It's value is <s>0.11111111111111111111111 x 2^-126 (note the exponent of denormalised numbers is always -126)
Normalised this would be <s>1.11111111111111111111110 x 2^-127 but -127 is out of range for EEEEEEEE


If we divide its value by 8 we get:

Code: Select all

sEEEEEEEEfffffffffffffffffffffff
s0000000000011111111111111111111
It's value is <s>0.00011111111111111111111 x 2^-126 (note the exponent of denormalised numbers is always -126)
Normalised this would be <s>1.11111111111111111110000 x 2^-130 but -130 is out of range for EEEEEEEE



So, for an example, take the following number:

Code: Select all

sEEEEEEEEfffffffffffffffffffffff
s0000000000000111000000000000000
It is a denormalised number since EEEEEEEE is zero and the fracional part is non-zero.
Its value is:
<s> 0.00000111000000000000000 x 2^-126

=<s> 1.11000000 x 2^-132 Normalised.. but the exponent of -132 is beyond the range that will allow this number to be stored in a normalised format.


Paul.

Posted: Sun May 28, 2006 7:43 pm
by Kale
Thanks Dioxin, thats cleared it up for me. :)

I'm guessing my code probably won't handle denormalised number then, as i always add the implied '1' at the front of all significands. Mind you, i'm guessing denormalised numbers in floats is pretty rare?

Posted: Mon May 29, 2006 10:45 am
by Trond
But why exactly would anyone want to know this?

Posted: Mon May 29, 2006 12:44 pm
by Kale
Trond wrote:But why exactly would anyone want to know this?
Education.

Posted: Mon May 29, 2006 1:00 pm
by Psychophanta
Kale wrote:
Trond wrote:But why exactly would anyone want to know this?
Education.
:D
I'd not call it education, but information :wink:
("Education" is a very subjetive concept)

BTW Thanks, Dioxin, nice info