--- /dev/null
+Samuel Tardieu
--- /dev/null
+USING: help.markup help.syntax ;
+IN: math.continued-fractions
+
+HELP: approx
+{ $values { "epsilon" "a positive floating point number representing the absolute acceptable error" } { "float" "a positive floating point number to approximate" } { "a/b" "a fractional number containing the approximation" } }
+{ $description "Give a rational approximation of " { $snippet "float" } " with a precision of " { $snippet "epsilon" } " using the smallest possible denominator." } ;
+
+HELP: >ratio
+{ $values { "seq" "a sequence representing a continued fraction" } { "a/b" "a fractional number" } }
+{ $description "Transform " { $snippet "seq" } " into its rational representation." } ;
+
+HELP: next-approx
+{ $values { "seq" "a mutable sequence" } }
+{ $description "Compute the next step in continued fraction calculation." } ;
--- /dev/null
+USING: kernel math.constants math.continued-fractions tools.test ;
+
+[ V{ 2 2.0 } ] [ V{ 2.5 } dup next-approx ] unit-test
+[ V{ 2 2 } ] [ V{ 2.5 } dup next-approx dup next-approx ] unit-test
+
+[ 5/2 ] [ V{ 2 2.1 } >ratio ] unit-test
+[ 5/2 ] [ V{ 2 1.9 } >ratio ] unit-test
+[ 5/2 ] [ V{ 2 2.0 } >ratio ] unit-test
+[ 5/2 ] [ V{ 2 2 } >ratio ] unit-test
+
+[ 3 ] [ 1 pi approx ] unit-test
+[ 22/7 ] [ 0.1 pi approx ] unit-test
+[ 355/113 ] [ 0.00001 pi approx ] unit-test
+
+[ 2 ] [ 1 2 approx ] unit-test
+[ 2 ] [ 0.1 2 approx ] unit-test
+[ 2 ] [ 0.00001 2 approx ] unit-test
+
+[ 3 ] [ 1 2.5 approx ] unit-test
+[ 5/2 ] [ 0.1 2.5 approx ] unit-test
+[ 5/2 ] [ 0.0001 2.5 approx ] unit-test
--- /dev/null
+! Copyright (C) 2009 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions sequences vectors ;
+IN: math.continued-fractions
+
+<PRIVATE
+
+: split-float ( f -- d i ) dup >integer [ - ] keep ;
+
+: closest ( seq -- newseq ) unclip-last round >integer suffix ;
+
+PRIVATE>
+
+: next-approx ( seq -- )
+ dup [ pop split-float ] [ push ] bi
+ dup zero? [ 2drop ] [ recip swap push ] if ;
+
+: >ratio ( seq -- a/b )
+ closest reverse unclip-slice [ swap recip + ] reduce ;
+
+: approx ( epsilon float -- a/b )
+ dup 1vector
+ [ 3dup >ratio - abs < ] [ dup next-approx ] while
+ 2nip >ratio ;
--- /dev/null
+Continued fractions