How to resolve the algorithm Continued fraction/Arithmetic/Construct from rational number step by step in the Mercury programming language
How to resolve the algorithm Continued fraction/Arithmetic/Construct from rational number step by step in the Mercury programming language
Table of Contents
Problem Statement
The purpose of this task is to write a function
r 2 c f
(
i n t
{\displaystyle {\mathit {r2cf}}(\mathrm {int} }
N
1
,
i n t
{\displaystyle N_{1},\mathrm {int} }
N
2
)
{\displaystyle N_{2})}
, or
r 2 c f
(
F r a c t i o n
{\displaystyle {\mathit {r2cf}}(\mathrm {Fraction} }
N )
{\displaystyle N)}
, which will output a continued fraction assuming: The function should output its results one digit at a time each time it is called, in a manner sometimes described as lazy evaluation. To achieve this it must determine: the integer part; and remainder part, of
N
1
{\displaystyle N_{1}}
divided by
N
2
{\displaystyle N_{2}}
. It then sets
N
1
{\displaystyle N_{1}}
to
N
2
{\displaystyle N_{2}}
and
N
2
{\displaystyle N_{2}}
to the determined remainder part. It then outputs the determined integer part. It does this until
a b s
(
N
2
)
{\displaystyle \mathrm {abs} (N_{2})}
is zero. Demonstrate the function by outputing the continued fraction for:
2
{\displaystyle {\sqrt {2}}}
should approach
[ 1 ; 2 , 2 , 2 , 2 , … ]
{\displaystyle [1;2,2,2,2,\ldots ]}
try ever closer rational approximations until boredom gets the better of you: Try : Observe how this rational number behaves differently to
2
{\displaystyle {\sqrt {2}}}
and convince yourself that, in the same way as
3.7
{\displaystyle 3.7}
may be represented as
3.70
{\displaystyle 3.70}
when an extra decimal place is required,
[ 3 ; 7 ]
{\displaystyle [3;7]}
may be represented as
[ 3 ; 7 , ∞ ]
{\displaystyle [3;7,\infty ]}
when an extra term is required.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Continued fraction/Arithmetic/Construct from rational number step by step in the Mercury programming language
Source code in the mercury programming language
%%%-------------------------------------------------------------------
:- module continued_fraction_from_rational.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int.
:- import_module list.
:- import_module string.
%%%-------------------------------------------------------------------
%%%
%%% ‘r2cf’ is a predicate, not a function. If it succeeds, it
%%% calculates not only the next digit, but the next starting
%%% fraction. If it fails, we are done.
%%%
:- pred r2cf(int::in, int::out, int::in, int::out, int::out)
is semidet.
r2cf(!N1, !N2, Digit) :-
(Dividend = !.N1),
(Divisor = !.N2),
(Divisor \= 0), % Fail if we have reached the end.
(!:N1 = Divisor), % The next Dividend.
(!:N2 = Dividend mod Divisor), % Floor division. The next divisor.
(Digit = Dividend div Divisor). % Floor division. The next digit.
%%%-------------------------------------------------------------------
%%%
%%% ‘r2cf_digits’ takes numerator and denominator of a rational
%%% number, and returns a list of continued fraction digits.
%%%
:- func r2cf_digits(int, int) = list(int).
:- pred r2cf_digits_loop(int::in, int::in,
list(int)::in, list(int)::out) is det.
r2cf_digits(N1, N2) = Digit_list :-
r2cf_digits_loop(N1, N2, [], Digit_list).
r2cf_digits_loop(N1, N2, !Digit_list) :-
(if r2cf(N1, N1_next, N2, N2_next, Digit)
then r2cf_digits_loop(N1_next, N2_next,
[Digit | !.Digit_list],
!:Digit_list)
else (!:Digit_list = reverse(!.Digit_list))).
%%%-------------------------------------------------------------------
%%%
%%% ‘print_cf’ prints a continued fraction nicely.
%%%
:- pred print_cf(list(int)::in, io::di, io::uo) is det.
:- pred print_cf_loop(list(int)::in, string::in, io::di, io::uo)
is det.
print_cf(Digit_list, !IO) :-
print_cf_loop(Digit_list, "[", !IO).
print_cf_loop(Digit_list, Sep, !IO) :-
(if (Digit_list = [Digit | More_digits])
then (print(Sep, !IO),
print(Digit, !IO),
(if (Sep = "[")
then print_cf_loop(More_digits, "; ", !IO)
else print_cf_loop(More_digits, ", ", !IO)))
else print("]", !IO)).
%%%-------------------------------------------------------------------
%%%
%%% ‘example’ takes numerator and denominator of a rational number,
%%% and prints a line of output.
%%%
:- pred example(int::in, int::in, io::di, io::uo) is det.
example(N1, N2, !IO) :-
print(N1, !IO),
print("/", !IO),
print(N2, !IO),
print(" => ", !IO),
print_cf(r2cf_digits(N1, N2), !IO),
nl(!IO).
%%%-------------------------------------------------------------------
main(!IO) :-
example(1, 2, !IO),
example(3, 1, !IO),
example(23, 8, !IO),
example(13, 11, !IO),
example(22, 7, !IO),
example(-151, 77, !IO),
example(14142, 10000, !IO),
example(141421, 100000, !IO),
example(1414214, 1000000, !IO),
example(14142136, 10000000, !IO),
example(31, 10, !IO),
example(314, 100, !IO),
example(3142, 1000, !IO),
example(31428, 10000, !IO),
example(314285, 100000, !IO),
example(3142857, 1000000, !IO),
example(31428571, 10000000, !IO),
example(314285714, 100000000, !IO),
true.
%%%-------------------------------------------------------------------
%%% local variables:
%%% mode: mercury
%%% prolog-indent-width: 2
%%% end:
%%%-------------------------------------------------------------------
:- module continued_fraction_from_rational_lazy.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module exception.
:- import_module integer. % Arbitrary-precision integers.
:- import_module lazy. % Lazy evaluation.
:- import_module list.
:- import_module string.
%% NOTE: There IS a "rational" module, for arbitrary-precision
%% rational numbers, but I wrote this example for plain "integer"
%% type. One could easily add "rational" support.
%%%-------------------------------------------------------------------
%%%
%%% The following lazy list implementation is suggested in the Mercury
%%% Library Reference.
%%%
:- type lazy_list(T)
---> lazy_list(lazy(list_cell(T))).
:- type list_cell(T)
---> cons(T, lazy_list(T))
; nil.
:- type cf == lazy_list(integer).
%%%-------------------------------------------------------------------
%%%
%%% r2cf takes numerator and denominator of a fraction, and returns a
%%% continued fraction as a lazy list of terms.
%%%
:- func r2cf(integer, integer) = cf.
r2cf(Numerator, Denominator) = CF :-
(if (Denominator = zero)
then (CF = lazy_list(delay((func) = nil)))
else (CF = lazy_list(delay(Cons)),
((func) = Cell :-
(Cell = cons(Quotient, r2cf(Denominator, Remainder)),
%% What follows is division with truncation towards zero.
divide_with_rem(Numerator, Denominator,
Quotient, Remainder))) = Cons)).
%%%-------------------------------------------------------------------
%%%
%%% cf2string and cf2string_with_max_terms convert a continued
%%% fraction to a printable string.
%%%
:- func cf2string(cf) = string.
cf2string(CF) = cf2string_with_max_terms(CF, integer(1000)).
:- func cf2string_with_max_terms(cf, integer) = string.
cf2string_with_max_terms(CF, MaxTerms) = S :-
S = cf2string_loop(CF, MaxTerms, zero, "[").
:- func cf2string_loop(cf, integer, integer, string) = string.
cf2string_loop(CF, MaxTerms, I, Accum) = S :-
(CF = lazy_list(ValCell),
force(ValCell) = Cell,
(if (Cell = cons(Term, Tail))
then (if (I = MaxTerms) then (S = Accum ++ ",...]")
else ((Separator = (if (I = zero) then ""
else if (I = one) then ";"
else ",")),
TermStr = to_string(Term),
S = cf2string_loop(Tail, MaxTerms, I + one,
Accum ++ Separator ++ TermStr)))
else (S = Accum ++ "]"))).
%%%-------------------------------------------------------------------
%%%
%%% example takes a fraction, as a string, or as separate numerator
%%% and denominator strings, and prints a line of output.
%%%
:- pred example(string::in, io::di, io::uo) is det.
:- pred example(string::in, string::in, io::di, io::uo) is det.
example(Fraction, !IO) :-
split_at_char(('/'), Fraction) = Split,
(if (Split = [Numerator])
then example_(Fraction, Numerator, "1", !IO)
else if (Split = [Numerator, Denominator])
then example_(Fraction, Numerator, Denominator, !IO)
else throw("Not an integer or fraction: \"" ++ Fraction ++ "\"")).
example(Numerator, Denominator, !IO) :-
example_(Numerator ++ "/" ++ Denominator,
Numerator, Denominator, !IO).
:- pred example_(string::in, string::in, string::in, io::di, io::uo)
is det.
example_(Fraction, Numerator, Denominator, !IO) :-
(N = integer.det_from_string(Numerator)),
(D = integer.det_from_string(Denominator)),
print(Fraction, !IO),
print(" => ", !IO),
print(cf2string(r2cf(N, D)), !IO),
nl(!IO).
%%%-------------------------------------------------------------------
main(!IO) :-
example("1/2", !IO),
example("3", !IO),
example("23/8", !IO),
example("13/11", !IO),
example("22/7", !IO),
example("-151/77", !IO),
%% I made "example" overloaded, so it can take separate numerator
%% and denominator strings.
example("151", "-77", !IO),
example("14142/10000", !IO),
example("141421/100000", !IO),
example("1414214/1000000", !IO),
example("14142136/10000000", !IO),
%% Decimal expansion of sqrt(2): see https://oeis.org/A002193
example("141421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", !IO),
example("31/10", !IO),
example("314/100", !IO),
example("3142/1000", !IO),
example("31428/10000", !IO),
example("314285/100000", !IO),
example("3142857/1000000", !IO),
example("31428571/10000000", !IO),
example("314285714/100000000", !IO),
%% Decimal expansion of pi: see https://oeis.org/A000796
example("314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", !IO),
true.
%%%-------------------------------------------------------------------
%%% local variables:
%%% mode: mercury
%%% prolog-indent-width: 2
%%% end:
You may also check:How to resolve the algorithm Golden ratio/Convergence step by step in the M4 programming language
You may also check:How to resolve the algorithm Averages/Arithmetic mean step by step in the V (Vlang) programming language
You may also check:How to resolve the algorithm Apply a callback to an array step by step in the Sparkling programming language
You may also check:How to resolve the algorithm Distribution of 0 digits in factorial series step by step in the Phix programming language
You may also check:How to resolve the algorithm Primality by Wilson's theorem step by step in the C++ programming language