# Fixed-point arithmetic (Forth)

### From LiteratePrograms

Forth has for a long time used fixed-point arithmetic for high-precision arithmetic. Forth is often targeted to microcontrollers which only have integer operations. It is only recently that Forth has gained a floating-point wordset for modern processors.

## Contents |

## Structure of a fixed point number

The idea is that the high-order bits in your word represent the integer portion of the number and the low order bits represent the fractional portion of the number. You can choose how many bits to use for each part depending on the accuracy required for your application. A common choice is to use 24 bits for integers and 8 bits for the fraction.

8constantfract-bits : int>fixed ( n -- f ) fract-bitslshift; : fixed>int ( f -- n ) fract-bitsrshift; 1 int>fixedconstant1F 1F 2/constant1/2F : fixed>fract ( f -- n ) 1F 1-and;

## Fixed point arithmetic

Fixed point addition and subtraction simply use integer addition and subtraction.

: fixed>round ( f -- n ) 1/2F + fixed>int ;

Fixed point multiplication and division require rescaling to get the number back into correct
range after using a double-precision multiply. The Forth word ***/** is tailored
for this operation. The intermediate multiply is double precision in order to avoid
overflow.

: *f ( f g -- f*g ) 1f */ ; : /f ( f g -- f/g ) 1fswap*/ ;

If you wish to multiply or divide a fixed-point number by a standard integer, then you can use the standard multiply and divide operators.

## Example: Mandelbrot set

As an example of fixed point use, here is a text mode Mandelbrot set generator.
It is using 18.14 fixed point numbers, and was used to test Open Firmware
implementations. (In Open Firmware, **>>a** is signed right shift and the
default base is hexadecimal.)

hex: f* * e >>a ; : sqoverdupf* ; 4666dupnegatedo4000dup2*negatedoij1ebegin1- ?dupwhile-rotsq sq2dup+ 10000 <while-i+ -rotf* 2*j+rotrepeat2dropdropblelsebla +thenemit2drop268 +loopcr5de +loop

Or in a more readable form which works on any ANS Forth:

<<mandelbrot.f>>=hex4000constant1fixed 4666constant1.1fixed 10000constant4fixeddecimal1fixed 3 * 80 /constantxinc 1.1fixed 2* 24 /constantyinc : *f ( f g -- f*g ) 1fixed */ ; : sq ( f -- f f*f )overdup*f ; : mandel 1.1fixeddupnegatedo1fixeddup2*negatedoij30 ( initial point x,y and max iteration count )begin1- ?dupwhile-rotsq sq2dup+ 4fixed <while-i+ -rot*f 2*j+rotrepeat2dropdrop\ exit from second whilespaceelse." *" \ exit from first whilethen2dropxinc +loopcryinc +loop; mandel

## Links

For more information in using fixed-point in Forth, see the chapter The Philosophy of Fixed Point in Leo Brodie's Forth primer Starting Forth.

Download code |