# Ratio

[![ version](](

This library allows you to use Rational numbers in Elixir, to enable exact calculations with all numbers big and small.

Ratio follows the Numeric behaviour from [Numbers](, and can therefore be used in combination with any data type that uses Numbers (such as [Tensor]( and [ComplexNum](

## Using Ratio

`Ratio` defines arithmetic and comparison operations to work with rational numbers.

Rational numbers can be created by using ``,
or by calling mathematical operators where one of the two operands is already a rational number.

### Shorthand infix construction operator

Since version 4.0, `Ratio` no longer defines an infix operator to create rational numbers.
Instead, rational numbers are made using ``,
and as the output from using an existing `Ratio` struct with a mathematical operation.

If you do want to use an infix operator such as
`<~>` (supported in all Elixir versions)
or `<|>` (deprecated in Elixir v1.14, the default of older versions of the `Ratio` library)

you can add the following one-liner to the module(s) in which you want to use it:

defdelegate numerator <~> denominator, to: Ratio, as: :new

### Basic functionality

Rational numbers can be manipulated using the functions in the [`Ratio`]( module.

iex> Ratio.mult(, 3),, 2)), 6)
iex> Ratio.div(, 3),, 5)), 12)
iex> Ratio.pow(, 4), 1)

The Ratio module also contains:
- a guard-safe `is_rational/1` check.
- a `compare/2` function for use with e.g. `Enum.sort`.
- `to_float/1` to (lossly) convert a rational into a float.

### Inline Math Operators and Casting

Ratio interopts with the [`Numbers`]( library:
If you want to overload Elixir's builtin math operators, 
you can add `use Numbers, overload_operators: true` to your module.

This also allows you to pass in a rational number as one argument
and an integer, float or Decimal (if you have installed the `Decimal` library),
which are then cast to rational numbers whenever necessary:

``` elixir
defmodule IDoAlotOfMathHere do
  defdelegate numerator <~> denominator, to: Ratio, as: :new
  use Numbers, overload_operators: true

  def calculate(input) do
     num = input <~> 2
     result = num * 2 + (3 <~> 4) * 5.0
     result / 2


``` elixir
iex> IDoAlotOfMathHere.calculate(42), 8)

## Installation

  The package can be installed from hex, by adding `:ratio` to your list of dependencies in `mix.exs`:

        def deps do
            {:ratio, "~> 4.0"}

## Changelog
- 4.0.1 - 
  - Fix compiler warnings on Elixir v1.16 (c.f. #128). Thank you, @kidq330
- 4.0.0 - 
  - Remove infix operator `<|>` as its usage is deprecated in Elixir v1.14. This is a backwards-incompatible change. If you want to use the old syntax with the new version, add `defdelegate num <|> denom, to: Ratio, as: :new` to your module. Alternatively, you might want to use the not-deprecated `<~>` operator for this instead.
  - Switch the `Inspect` implementation to use the form `, 20)` instead of `10 <|> 20`, related to above. This is also a backwards-incompatible change.
  - Remove implementation of `String.Chars`, as the earlier implementation was not a (non-programmer) human-readable format.
  - Ensure that the right-hand-side operand of calls to `Ratio.{add, sub, mult, div}/2` is allowed to be an integer for ease of use and backwards compatibility. Thank you for noticing this problem, @kipcole9 ! (c.f. #111)
- 3.0.2 - 
  - Fixes: A bug with `<|>` when the numerator was a rational and the denuminator an integer. (c.f. #104) Thank you, @varsill!
- 3.0.1 -
  - Fixes:
    - Problem where `Ratio.ceil/1` would be off-by-one (c.f. #89). Thank you, @Hajto!
    - Problem where `Ratio.pow/2` would return an integer rather than a new Ratio.(c.f. #100). Thank you, @speeddragon!
- 3.0.0 - 
  - All operators except `<|>` are removed from Ratio. Instead, the operators defined by [`Numbers`]( (which `Ratio` depends on) can be used, by adding `use Numbers, overload_operators: true` to your modules. (c.f. #34)
  - All math-based functions expect and return `Ratio` structs (rather than also working on integers and returning integers sometimes if the output turned out to be a whole number).  (c.f. #43)
    This makes the code more efficient and more clear for users.
    - Ratio structs representing whole numbers are no longer implicitly converted 'back' to integers, as this behaviour was confusing. (c.f. #28)
    - If conversion to/from other number-like types is really desired, 
      use the automatic conversions provided by ``, `<|>` 
      or (a bit slower but more general) the math functions exposed by [`Numbers`](
      Ratio ships with implementations of `Coerce.defcoercion` for Integer -> Ratio, Float -> Ratio and Decimal -> Ratio.
  - `is_rational?/1` is replaced with the guard-safe `is_rational/1` (only exported on Erlang versions where `:erlang.map_get/2` is available, i.e. >= OTP 21.0.) (c.f. #37)
  - `Float.ratio/1` is now used to convert floats into `Ratio` structs, rather than maintaining a hand-written version of this logic. (c.f #46) Thank you, @marcinwasowicz !
  - A lot of property-based tests have been added to get some level of confidence of the correctness of the library's operations.
- 2.4.2 Uses `extra_applications` in `mix.exs` to silence warnings in Elixir 1.11 and onwards.
- 2.4.1 Fixes a bug in the decimal conversion implementation where certain decimals were not converted properly. Thank you, @iterateNZ!
- 2.4.0 Adds optional support for automatic conversion from [Decimal]( Thank you, @kipcole !
- 2.3.1 Removes spurious printing statement in `Rational.FloatConversion` that would output a line of text at compile-time. Fixes support for Numbers v5+ which was broken.
- 2.3.0 Adds `trunc` and `to_floor_error` functions.
- 2.1.1 Fixes implementation of `floor` and `ceil` which was counter-intuitive for negative numbers (it now correctly rounds towards negative infinity). 
  - Drops support for Elixir versions older than 1.4, because of use of `Integer.floor_div`.
  - First version to support new Erlang versions (20 and onward) that have native `floor` and `ceil` functions.
- 2.1.0 Adds optional overloaded comparison operators.
- 2.0.0 Breaking change: Brought `` in line with Elixir's comparison function guideline, to return `:lt | :eq | :gt`. (This used to be `-1 | 0 | 1`).
- 1.2.9 Improved documentation. (Thanks, @morontt!)
- 1.2.8 Adding `:numbers` to the `applications:` list, to ensure that no warnings are thrown when building releases on Elixir < 1.4.0.
- 1.2.6, 1.2.7 Improving documentation.
- 1.2.5 added `ceil/1` and `floor/1`.
- 1.2.4 Fixes Elixir 1.4 warnings in the `mix.exs` file.
- 1.2.3 Upgraded version of the `Numbers` dependency to 2.0.
- 1.2.2 Added default argument to ``, to follow the Numeric behaviour fully, and added `Ratio.minus/1` as alias for `Ratio.negate/1` for the same reason.
- 1.2.0 Changed name of `Ratio.mul/2` to `Ratio.mult/2`, to avoid ambiguety, and to allow incorporation with `Numbers`. Deprecation Warning was added to using `Ratio.mul/2`.
- 1.1.1 Negative floats are now converted correctly.
- 1.1.0 Elixir 1.3 compliance (Statefree if/else/catch clauses, etc.)
- 1.0.0 Proper `__using__` macro, with more readable option names. Stable release.
- 0.6.0 First public release
- 0.0.1 First features

## Difference with the 'rational' library

Observant readers might notice that there also is a '[rational](' library in The design idea between that library vs. this one is a bit different: `Ratio` hides the internal data representation as much as possible, and numbers are therefore only created using ``. This has as mayor advantage that the internal representation is always correct and simplified.

The Ratio library also (optionally) overrides (by virtue of the `Numbers` library) the built-in math operations `+, -, *, /, div, abs` so they work with combinations of integers, floats and rationals.

Finally, Ratio follows the Numeric behaviour, which means that it can be used with any data types that follow [Numbers](