Skip to content

erlsci/rationals

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rationals

Build Status Coverage Tag Erlang Versions

Rational numbers in Erlang

Project Logo

Build & Test

rebar3 compile
rebar3 check

Usage

1> Third = rationals:new(1, 3).
{fraction,1,3}
2> Quarter = rationals:new(1, 4).
{fraction,1,4}
3> rationals:numerator(Quarter).
1
4> rationals:denominator(Quarter).
4
5> rationals:add(Quarter, Third).
{fraction,7,12}
6> rationals:multiply(Quarter, Third).
{fraction,1,12}

Arithmetic returns unreduced fractions; call reduce/1 (or normalize/1) for canonical form — reduced to lowest terms with the sign on the numerator and a positive denominator:

7> Sum = rationals:add(rationals:new(3, 4), rationals:new(5, 12)).
{fraction,56,48}
8> rationals:reduce(Sum).
{fraction,7,6}
9> rationals:normalize(rationals:new(1, -2)).
{fraction,-1,2}

The constants zero/0 and one/0 return canonical 0/1 and 1/1:

10> rationals:zero().
{fraction,0,1}
11> rationals:one().
{fraction,1,1}

Compare fractions by value with compare/2 (which returns lt, eq, or gt) or with the boolean predicates gt/2, lt/2, eq/2, gte/2, and lte/2:

12> rationals:compare(Quarter, Third).
lt
13> rationals:gt(Third, Quarter).
true
14> rationals:eq(rationals:new(2, 4), rationals:new(1, 2)).
true

Negate, absolute value, and sign:

15> rationals:negate(Quarter).
{fraction,-1,4}
16> rationals:abs(rationals:new(-3, 4)).
{fraction,3,4}
17> rationals:sign(rationals:new(-3, 4)).
-1

Integer exponentiation, sum, and product:

18> rationals:pow(rationals:new(2, 3), 3).
{fraction,8,27}
19> rationals:pow(rationals:new(2, 3), -1).
{fraction,3,2}
20> rationals:sum([rationals:new(1, 2), rationals:new(1, 3), rationals:new(1, 6)]).
{fraction,6,6}
21> rationals:reduce(rationals:sum([rationals:new(1, 2), rationals:new(1, 3), rationals:new(1, 6)])).
{fraction,1,1}
22> rationals:product([rationals:new(2, 3), rationals:new(3, 4)]).
{fraction,6,12}

Rounding and integer conversion — floor/1 rounds toward −∞, ceil/1 toward +∞, truncate/1 toward zero, and round/1 rounds half away from zero:

23> rationals:floor(rationals:new(-7, 2)).
-4
24> rationals:ceil(rationals:new(-7, 2)).
-3
25> rationals:round(rationals:new(5, 2)).
3

Mixed-number decomposition and predicates:

26> rationals:to_mixed(rationals:new(7, 3)).
{2,{fraction,1,3}}
27> rationals:from_mixed(2, 1, 3).
{fraction,7,3}
28> rationals:is_integer(rationals:new(6, 3)).
true
29> rationals:is_proper(rationals:new(3, 4)).
true

Parse fractions from text and format them as binaries:

30> rationals:parse("3/4").
{ok,{fraction,3,4}}
31> rationals:parse("-7/3").
{ok,{fraction,-7,3}}
32> rationals:parse("42").
{ok,{fraction,42,1}}
33> rationals:parse("3/0").
{error,zero_denominator}
34> rationals:format(rationals:new(7, 12)).
<<"7/12">>
35> rationals:format(rationals:new(3, 1)).
<<"3">>
36> rationals:from_integer(5).
{fraction,5,1}

Continued fractions, convergents, and best rational approximation:

37> rationals:continued_fraction(rationals:new(7, 3)).
[2,3]
38> rationals:convergents(rationals:new(7, 3)).
[{fraction,2,1},{fraction,7,3}]
39> rationals:rationalize(3.14159, 0.001).
{fraction,22,7}
40> rationals:mediant(rationals:new(1, 2), rationals:new(1, 3)).
{fraction,2,5}

Exact decimal expansion (non-repeating + repeating block):

41> rationals:decimal_expansion(rationals:new(1, 6)).
{<<"0.1">>,<<"6">>}
42> rationals:decimal_expansion(rationals:new(2, 7)).
{<<"0.">>,<<"285714">>}

Egyptian fraction decomposition and Farey sequences:

43> rationals:egyptian(rationals:new(2, 3)).
[{fraction,1,2},{fraction,1,6}]
44> rationals:farey(3).
[{fraction,0,1},{fraction,1,3},{fraction,1,2},{fraction,2,3},{fraction,1,1}]

Also available: min/2, max/2, clamp/3, between/3, dist/2, is_zero/1, is_positive/1, is_negative/1, is_reduced/1, is_unit_fraction/1, lcm/2, from_continued_fraction/1.

23> rationals:gcd(64, 72).
8

The original long-form names — simplify/1, is_greater_than/2, is_less_than/2, is_equal_to/2, is_greater_or_equal/2, and is_less_or_equal/2 — remain available as backward-compatible aliases, but the short names above are preferred.

See more examples in test/rationals_SUITE.erl; see rationals.erl for implementation details.

Behavior change in 0.3.0: negative-denominator canonicalization

reduce/1 (and its alias simplify/1) now canonicalize sign: the denominator is always positive in the result and the sign is carried on the numerator. Previously, reduce(new(1, -2)) returned 1/-2; it now returns -1/2. compare/2 and all derived predicates are now sign-robust — they normalize operands internally, so comparisons are correct even on fractions with a negative denominator.

License

Copyright © 2021-2026, Erlang-Aided Enrichment Center

Copyright © 2014 Peter Morgan peter.james.morgan@gmail.com

About

Rational numbers in Erlang

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Erlang 96.0%
  • Makefile 4.0%