# Re: Factor

Factor: the language, the theory, and the practice.

## Floating-point Fractions

Tuesday, August 31, 2010

Recently, I wanted a way to convert floating-point numbers into fractions using Factor. To do this (with any hope of being correct), I spent some time understanding how floating-point numbers are represented.

Two useful resources about floating-point numbers are an article entitled “What Every Computer Scientist Should Know About Floating-Point Arithmetic” and a website called The Floating-Point Guide.

Basic floating-point numbers are specified using a sign bit, an exponent, and a mantissa. Aside from some special numbers (e.g., +Inf, -Inf, NaN) and denormal numbers, the value of a floating-point can be calculated using the formula:

(-1)sign × 2exponent\ -\ exponent\ bias × 1.mantissa

We will be working with double precision floating point values (e.g., 64-bit values): To extract the sign, exponent, and mantissa bits is fairly easy:

``````USING: kernel math math.bitwise math.functions ;

: sign ( bits -- sign )
-63 shift ;

: exponent ( bits -- exponent )
-52 shift 11 on-bits mask ;

: mantissa ( bits -- mantissa )
``````

We are not going to support special values, so we throw an error if we encounter one:

``````: check-special ( n -- n )
dup fp-special? [ "cannot be special" throw ] when ;
``````

Converting to a ratio (e.g., numerator and denominator) is just a matter of computing the formula (with some special handling for denormal numbers where the exponent is zero):

``````: float>ratio ( n -- a/b )
check-special double>bits
[ sign zero? 1 -1 ? ] [ mantissa 52 2^ / ] [ exponent ] tri
dup zero? [ 1 + ] [ [ 1 + ] dip ] if 1023 - 2 swap ^ * * ;
``````

You can see this in action:

``````IN: scratchpad 0.5 float>ratio .
1/2