Floating Point number format

From BeebWiki
Jump to: navigation, search

Description

BBC BASIC stores real (non-integer) numbers in five bytes in a format known as "five-byte floating point". This splits the number into two components - a one-byte exponent and a four-byte mantissa.

All numbers, other than zero, can be expressed as m*10^e. You may be familiar with this form known as exponential format. For example:

    100 is 1*10^2
   5000 is 5*10^3
    0.5 is 5*10^-1

Exactly the same can be done using base 2, expressing numbers as m*2^e, for example:

      4 is   1*2^2
     -8 is  -1*2^3
     12 is 1.5*2^3
   -0.5 is  -1*2^-1

In floating point format, the manitissa is normalised by being multiplied or divided by 2, and the exponent reduced or increased, until the mantissa m is in the range 0.5 to 1, excluding 1, for example:

      4 is  0.5*2^3
     -8 is -0.5*2^4
     12 is 0.75*2^4
   -0.5 is -0.5*2^0

Normalising the mantissa means that the first bit of the mantissa is always 1. That means that as we know it will always be 1, it can be used to hold something else, and it is used to hold the sign bit.

To allow negative exponents an excess is added to it. Acorn BASICs use excess &80, where &80 represents an exponent of 0; Russell BASICs uses excess &7F, where &7F represents an exponent of 0. This can be represented as:

   7       0     31                                  0
  +-+-------+    +-+-------+--------+--------+--------+
  |S|eeeeeee|    |S|mmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|
  +-+-------+    +-+-------+--------+--------+--------+
 sign exponent  sign        implied-1 mantissa

So, for example on Acorn BASICs:

      4 is exponent &83, sign 0, mantissa &80000000, stored as &83,&00000000
     -8 is exponent &84, sign 1, mantissa &80000000, stored as &84,&00000000
     12 is exponent &84, sign 0, mantissa &C0000000, stored as &84,&40000000
   -0.5 is exponent &80, sign 1, mantissa &80000000, stored as &80,&80000000

Zero is a special case and is stored as five zero bytes. Some versions of BBC BASIC extend this and use a zero exponent to indicate that the real actually holds an integer value. For example:

   &00, &00000000 is 0
   &00, &00000080 is 128 (where implemented)
   &00, &FFFFFFFE is -2  (where implemented)

To convert a real to an integer the mantissa must be multiplied by two and the exponent consequently decreased until the exponent is zero (ie &80 on Acorn BASICs, &7F on Russell BASICs), a process known as denormalisation. For example, converting 0.5*2^3 back to 4*2^0.

Of course, if the real holds a noninteger, then when the mantissa is multiplied some bits will overflow before the exponent has reached zero. Depending on what you want to do with the denormalised number, a program would either ignore those overflowed bits, giving a truncated integer, or the overflow flags an error to indicate that the real could not be denormalised to an integer.

Implementations

6502 BASIC

6502 BASIC stores reals in memory high-to-low as:

   address+0                                                  address+4
   mantissa.hi, mantissa.middle, mantissa.middle, mantissa.lo, exponent

The only 32-bit integer that 6502 BASIC allows to be stored in a real is zero. 6502 BASIC uses excess-&80 for the exponent, so &80 represents an exponent of zero.

Non-6502 BASICs

All other versions of BBC BASIC store reals in memory low-to-high as:

   address+0                                                  address+4
   mantissa.lo, mantissa.middle, mantissa.middle, mantissa.hi, exponent

Acorn BASICs use excess-&80 for the exponent, so &80 represents an exponent of zero. Zero is the only 32-bit integer than can be stored in a real by setting the exponent to zero.

Russell BASICs use excess-&7F for the exponent, so &7F represents an exponent of zero. Any 32-bit integer can be stored in a real by setting the exponent to zero.

J.G.Harston's PDP-11 BASIC stores reals in memory low-to-high, and allows 32-bit integers to be stored by setting the exponent to zero, as in Russell BASICs.

Where an exponent of zero can be used to store an integer, that means that if num is an integer and stored in memory with |address=num then |address=!address. If num is less than 256, then |address=!address=?address. Similarly, if num is stored in memory with !address=num:address?4=0 then, again, |address=!address.

64-bit BASIC

ARM BASIC VI and Windows BASIC can use 8-byte floating point numbers.

See Also

Jgharston 23:26, 30 April 2008 (BST) Jgharston (talk) 02:30, 10 July 2021 (CEST)