View Source Rationalize.Rational (Rationalize v0.1.0)

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.

examples

Examples

iex> alias Rationalize.Rational, as: R iex> R.compare(R.new(1, 2), R.new(2, 1)) :lt iex> R.compare(R.new(2, 1), R.new(1, 2)) :gt iex> R.compare(R.new(1, 1), R.new(1, 1)) :eq iex> R.compare(R.new(1, 0), R.new(1, 2)) :gt iex> R.compare(R.new(-1, 0), R.new(-1, 2)) :lt

Notes

  • While shortcuts may be possible, the explicit branches are easy to follow.
@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> alias Rationalize.Rational, as: R iex> R.compare_to_num(R.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> alias Rationalize.Rational, as: R iex> R.mediant(R.new(1, 4), R.new(1, 2)) %R{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> alias Rationalize.Rational, as: R iex> R.standardize(R.new(1, 2)) %R{n: 1, d: 2} iex> R.standardize(R.new(1, -2)) %R{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> alias Rationalize.Rational, as: R iex> R.to_string(R.new(1, 2)) "1/2" iex> R.to_string(R.new(1, 2), fn n, d -> "#{n} over #{d}" end) "1 over 2"