View Source Rationalize.Rational (Rationalize v0.1.1)

Construct and safely manipulate rational numbers.

A rational number is defined by its integer numerator and denominator, each of which may be positive, negative, or zero. A denominator of 0 is perfectly acceptable for a rational number as long floating point division is avoided.

Link to this section Summary

Functions

Compare two rational numbers. The result is :gt, :lt, or :eq if the first argument is, respectively, greater than, less than, or equal to the second argument. The comparison is done in a way that avoids conversion to a finite-precision float.

Compare a rational number to an ordinary number (integer or float). The result is :gt, :lt, or :eq if the rational is, respectively, greater than, less than, or equal to the float.

Attempt to compute the difference between a rational number and a float. Arguments can be supplied in either order.

Return the mediant of two rational numbers. If n1/d1 and n2/d2 are two rational numbers, then

Negate a rational by negating the numerator. Note that this does the right thing when the denominator is 0.

Create a new Rational struct given integer values for the numerator and denominator. An exception is raised if the numerator or denominator is not an integer.

Standardize a rational number such that the denominator is never negative. The result is numerically equivalent to the original rational, but not syntactically equivalent.

Attempt to convert a rational number to a float.

Return a string representation of a rational number using a provided format.

Link to this section Types

@type comparison() :: :gt | :lt | :eq | :undefined
@type option_float() :: {:ok, float()} | :pos_infinity | :neg_infinity | :undefined
@type t() :: %Rationalize.Rational{d: integer(), n: integer()}

Link to this section Functions

@spec compare(t(), t()) :: comparison()

Compare two rational numbers. The result is :gt, :lt, or :eq if the first argument is, respectively, greater than, less than, or equal to the second argument. The comparison is done in a way that avoids conversion to a finite-precision float.

The result is :undefined if one of the arguments has numerator and denominator equal to zero, or if both arguments have a denominator of 0.

A rational with a denominator of 0 and a positive numerator is greater than any rational with a nonzero denominator. Similarly, a rational with a denominator of 0 and a negative numerator is less than any rational with a nonzero denominator.

Notes

  • While shortcuts may be possible, the explicit branches are easy to follow.

examples

Examples

iex> Rationalize.Rational.compare(Rationalize.Rational.new(1, 2), Rationalize.Rational.new(2, 1))
:lt

iex> Rationalize.Rational.compare(Rationalize.Rational.new(2, 1), Rationalize.Rational.new(1, 2))
:gt

iex> Rationalize.Rational.compare(Rationalize.Rational.new(1, 1), Rationalize.Rational.new(1, 1))
:eq

iex> Rationalize.Rational.compare(Rationalize.Rational.new(1, 0), Rationalize.Rational.new(1, 2))
:gt

iex> Rationalize.Rational.compare(Rationalize.Rational.new(-1, 0), Rationalize.Rational.new(-1, 2))
:lt
@spec compare_to_num(t(), number()) :: comparison()
@spec compare_to_num(number(), t()) :: comparison()

Compare a rational number to an ordinary number (integer or float). The result is :gt, :lt, or :eq if the rational is, respectively, greater than, less than, or equal to the float.

The result is :undefined if the numerator and denominator of the rational are both 0.

A rational with a denominator of 0 and a positive numerator is greater than any number. Similarly, a rational with a denominator of 0 and a negative numerator is less than any number.

examples

Examples

iex> Rationalize.Rational.compare_to_num(Rationalize.Rational.new(1, 2), 1)
:lt
@spec diff_num(t(), number()) :: option_float()
@spec diff_num(number(), t()) :: option_float()

Attempt to compute the difference between a rational number and a float. Arguments can be supplied in either order.

This returns {:ok, <float diff>} when the rational can be converted to a finite float. If the denominator of the rational is 0, this returns :undefined if the numerator is also 0, :pos_inifinity if the numerator is greater than 0, or :neg_infinity if the numerator is less than 0.

Link to this function

mediant(rational1, rational2)

View Source
@spec mediant(t(), t()) :: t()

Return the mediant of two rational numbers. If n1/d1 and n2/d2 are two rational numbers, then

mediant(n1/d1, n2/d2) = (n1 + n2)/(d1 + d2)

The mediant has the property

n1/d1 < (n1 + n2)/(d1 + d2) < n2/d2

when n1/d1 < n2/d2.

examples

Examples

iex> Rationalize.Rational.mediant(Rationalize.Rational.new(1, 4), Rationalize.Rational.new(1, 2))
%Rationalize.Rational{n: 2, d: 6}
@spec negate(t()) :: t()

Negate a rational by negating the numerator. Note that this does the right thing when the denominator is 0.

@spec new(integer(), integer()) :: t()

Create a new Rational struct given integer values for the numerator and denominator. An exception is raised if the numerator or denominator is not an integer.

@spec standardize(t()) :: t()

Standardize a rational number such that the denominator is never negative. The result is numerically equivalent to the original rational, but not syntactically equivalent.

examples

Examples

iex> Rationalize.Rational.standardize(Rationalize.Rational.new(1, 2))
%Rationalize.Rational{n: 1, d: 2}

iex> Rationalize.Rational.standardize(Rationalize.Rational.new(1, -2))
%Rationalize.Rational{n: -1, d: 2}
@spec to_float(t()) :: option_float()

Attempt to convert a rational number to a float.

This returns {:ok, <float value>} for the given rational number if the denominator is nonzero. If the denominator is 0, this returns :undefined if the numerator is also 0, :pos_inifinity if the numerator is greater than 0, or :neg_infinity if the numerator is less than 0.

Link to this function

to_string(rational, formatter \\ fn n, d -> "#{n}/#{d}" end)

View Source
@spec to_string(t(), (integer(), integer() -> binary())) :: binary()

Return a string representation of a rational number using a provided format.

The default format is "<numerator>/<denominator>", but this can be customized by providing a function that takes the numerator and denominator and returns a string.

examples

Examples

iex> Rationalize.Rational.to_string(Rationalize.Rational.new(1, 2))
"1/2"

iex> Rationalize.Rational.to_string(Rationalize.Rational.new(1, 2), fn n, d -> "#{n} over #{d}" end)
"1 over 2"