• Stars
    star
    39
  • Rank 669,082 (Top 14 %)
  • Language
    Elixir
  • License
    MIT License
  • Created about 8 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rational number library for Elixir.

Ratio

hex.pm version Documentation ci

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 Ratio.new/2, 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 Ratio.new, 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(Ratio.new(1, 3), Ratio.new(1, 2))
Ratio.new(1, 6)
iex> Ratio.div(Ratio.new(2, 3), Ratio.new(8, 5))
Ratio.new(5, 12)
iex> Ratio.pow(Ratio.new(2), 4)
Ratio.new(16, 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:

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
  end
end
iex> IDoAlotOfMathHere.calculate(42)
Ratio.new(183, 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"}
      ]
    end

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 Ratio.new(10, 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 Ratio.new, <|> 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 Decimals. 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 Ratio.compare/2 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 Ratio.new/2, 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 Hex.pm. 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 Ratio.new/2. 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.

More Repositories

1

elixir-type_check

TypeCheck: Fast and flexible runtime type-checking for your Elixir projects.
Elixir
510
star
2

elixir-tensor

The Tensor library adds support for Vectors, Matrixes and higher-dimension Tensors to Elixir.
Elixir
140
star
3

elixir-map_diff

Calculates the difference between two (nested) maps, and returns a map representing the patch of changes.
Elixir
116
star
4

elixir-arrays

Well-structured Arrays with fast random-element-access for Elixir, offering a common interface with multiple implementations with varying performance guarantees that can be switched in your configuration.
Elixir
76
star
5

ruby-prop_check

Property Testing library in Ruby
Ruby
70
star
6

elixir-fun_land

Algebraic Data Types for Elixir: Both functional and fun.
Elixir
69
star
7

elixir-capture_pipe

A pipe-macro for Elixir that allows bare function captures
Elixir
45
star
8

elixir-currying

Currying enables partial function application in Elixir.
Elixir
41
star
9

raii_with

A simple library to provide RAII in standard-compliant C99, using raii_with(resource, initializer, destructor) { ... }-syntax:
C
39
star
10

elixir-number

Numbers -- A generic wrapper to use *any* custom Numeric type in Elixir!
Elixir
36
star
11

elixir-specify

A library to create Comfortable, Explicit, Multi-Layered and Well-Documented Specifications for all your configurations, settings and options in Elixir.
Elixir
33
star
12

c_exceptional

A simple Exception-handling library for C99, that uses some fancy macros for true try{...}catch(err){...}finally{...} syntax!
C++
33
star
13

elixir-blocked

An Elixir-library that helps you to keep track of when hotfixes can be removed by showing compile-time warnings when issues (in your project repository or any other source-code GitHub repository) are closed.
Elixir
29
star
14

elixir-okasaki

Multiple different implementations of efficient functional queues and dequeues for Elixir
Elixir
28
star
15

elixir-revisionair

Keep track of your data structure's revisions, persistence layer agnostic.
Elixir
26
star
16

elixir-sequences

Defines a module containing many common integer sequences (even numbers, odd numbers, primes, factorials, fibonacci, etc)
Elixir
21
star
17

elixir-rustler_elixir_fun

Calling Elixir or Erlang functions from native code written in Rust
Rust
20
star
18

elixir-agarex

An example game for the presentation "Multiplayer Games & Collaborative Editing with Phoenix LiveView" which was written for ElixirConf.EU 2020.
Elixir
20
star
19

inscryption-secrets-hints

19
star
20

js1k_powder_game

JavaScript
18
star
21

elixir-revisionair_ecto

A Revisionair adapter based on Ecto. Allows you to persist and keep track of revisions of your data structures in any of Ecto's supported databases.
Elixir
18
star
22

elixir-tea_vent

Elixir library to do event-dispatching in an Event Sourcing and The Elm Architecture-like way
Elixir
16
star
23

elixir-solution

A Macro-based approach to ease working with ok/error tuples in Elixir
Elixir
16
star
24

elixir-prioqueue

Priority Queues for Elixir.
Elixir
15
star
25

elixir_gen_frp

Elixir
15
star
26

cpp-parser_combinators

An example of how to construct a parser combinator library in C++. Focus on simplicity, not efficiency.
C++
14
star
27

elixir-riak_ecto3

RiakEcto3 is an Elixir Ecto 3 Adapter for the Riak KV database (For Riak KV v 2.0 and upward).
Elixir
13
star
28

Jux

Elixir
12
star
29

elixir_persistent_gen_server

Elixir
11
star
30

ExtremeBytebeats

A collection of bytebeat programs, some of them rather involved.
JavaScript
11
star
31

elixir_complex_num

Complex Numbers for Elixir, wrapping not only floats but _any_ kind of numeric data type.
Elixir
11
star
32

elixir-arrays_aja

Provides an `Arrays` implementation for `Aja`'s `Vector` datatype, which is an implementation of a 'Hickey Trie' Vector written in Elixir.
HTML
8
star
33

elixir-orderable

A protocol for making your custom datastructures orderable (for sorting and comparing.).
Elixir
7
star
34

rust-overloaded_literals

Rust crate: Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation.
Rust
7
star
35

rust-backdrop_arc

An Arc (atomically reference counted smart pointer) that supports customized dropping strategies using Backdrop.
Rust
5
star
36

LastMail

LastMail is the world's first passive post-mortem message system. It lets you send a good-bye to your friends and contacts, and pass on your (digital) belongings.
PHP
4
star
37

elixir-unicode

The Elixir Unicode package provides functionality to check properties of unicode codepoints, graphemes and strings.
Elixir
4
star
38

elixir_ordered_siblings

Ordered Siblings: Allows reordering (in Ecto) of comments under posts, images under albums, songs under playlists, etc.
Elixir
4
star
39

elixir_guard_safe_modulo

The ridiculous guard-safe implementation for a floored modulo operation.
Elixir
4
star
40

rust-backdrop

Drop your large or complex Rust objects in the background using Backdrop!
Rust
4
star
41

SimpleRNG

A very simple Xorshift-based RNG, whose goal is to reproduce the same results regardless of platform, language or environment
Haskell
4
star
42

JS-CoinStackBar

A customizable vertical progress bar in the shape of a stack of coins.
JavaScript
3
star
43

elixir-cubdb_nerves_example

An example of using CubDB with Nerves
Elixir
3
star
44

elixir-extractable

A lightweight reusable Extractable protocol for Elixir, allowing extracting elements one-at-a-time from a collection.
Elixir
3
star
45

elixir-fun_landic

Implementations of common Algorithmic Data Types for Elixir, built on top of the `fun_land` interface.
Elixir
3
star
46

ruby-doctest2

Doctests (documentation testing) for Ruby
Ruby
3
star
47

elixir-password-bloomex

Example of using a bloom filter to check for prohibited passwords
Elixir
3
star
48

elixir-sets

Sets for Elixir, with a single interface and varying implementations.
Elixir
3
star
49

photoboothy

Nerves Rpi 3 Photobooth
JavaScript
3
star
50

rust-slimmer_box

`SlimmerBox<T>` is a packed alternative to `Box<T>` whose 'fat' pointer is 'slimmer'
Rust
3
star
51

elixir-insertable

A lightweight reusable Insertable protocol for Elixir, allowing inserting elements one-at-a-time into a collection.
Elixir
3
star
52

elixir-benchmarking_then_genserver

A test to benchmark the performance of `Kernel.then/2` when running it in a semi 'real-life' scenario when managing the state of a GenServer
Erlang
2
star
53

elixir-stream_data-property-example

Example of how I'd like to nest multiple properties together with the stream_data library
Elixir
2
star
54

c_treat

A proof-of-concept Trait system for C
C
2
star
55

alchemud

An (very early, very crude) to write a Multi-User-Dungeon in Elixir
Elixir
2
star
56

concurrency_elixir_slides

This repository contains both the code snippets as well as the slides from my presentation "A Winner is You: Concurrency in Elixir"
Elixir
2
star
57

elixir-sliding_window

Elixir 'Sliding Window'
Elixir
2
star
58

haskell-vary

A fast and user-friendly implementation of variant types (aka open unions, open sum types, coproducts)
Haskell
2
star
59

rust-bassert

Better assertions for Rust
Rust
2
star
60

python-multiple_indexed_collection

A collection type for arbitrary objects, that indexes them based on (a subset of) their properties.
Python
2
star
61

elixir-arrays_rrb_vector

Wraps Rust's `im::Vector`, an immutable Relaxed-Radix-Balanced Trie-based vector, for usage with the Elixir `Arrays` library
HTML
2
star
62

rust-naperian

(Experimental) Rust implementation of the paper 'APLicative programming using Naperian functors'
Rust
2
star
63

EpicAuth

Epic! Auth!
Ruby
1
star
64

cc_freeops

An implementation of automatic free binary operator generation when their respective compound operators are known.
Forth
1
star
65

elixir-test-benchmrking_then

A test repo to benchmark the overhead of Kernel.then/2
Elixir
1
star
66

elixir-coerce

Automatic coercion of types that can be promoted to each-other for Elixir.
Elixir
1
star
67

elixir-iter

Iterators for Elixir datastructures
Elixir
1
star
68

cpp-traits-with-variants

Example of how to implement Traits in C++ that also work when constructing a collection of trait-implementing objects.
C++
1
star
69

okasaki_benchmark

Elixir
1
star
70

cpp-thunk

Experimental code to do lazy (i.e. on-demand) evaluation of values in C++
C++
1
star
71

elixir-enum_benchmark_example

Microbenchmark comparing the Elixir iteration abstractions for, enum and iter
Elixir
1
star
72

Haskell-sound-playing

A simple example of how to use the SDL2 Haskell bindings to play sound files (as a complete Stack setup with dependencies, because that was most of the hassle)
Haskell
1
star
73

elixir_online-game

A proof-of-concept online game, to test scalability of having many concurrent player-states updating.
Elixir
1
star
74

rust-polars_s3

POC to write to Object Stores like S3 with Polars
Rust
1
star
75

ifs_zoom

W-M's Bachelor Project about IFS zooming
HTML
1
star
76

elixir-experimental_comparable

An experimental implementation of a possible Comparable protocol for Elixir.
Elixir
1
star
77

haskell-snek

A simple implementation of Snake. Runs in a terminal
Haskell
1
star
78

roc-bf_example

A simple (and incomplete) example of a BrainFukc interpreter in the Roc programming language.
LLVM
1
star
79

symmath

Elixir
1
star
80

elixir_calendrical

Elixir
1
star
81

c_hash_map

A very simple HashMap-implementation in C
C
1
star
82

riak-cluster-test

Repository of code about running a Riak cluster using docker
1
star
83

presentation-communicating_between_ruby_and_elixir

Presentation on how you can communicate between a separately running Ruby system and Elixir system, as we do it in Planga.io
JavaScript
1
star
84

haskell-MonotonicityTypes

An implementation of 'Sfuns', functions that keep track of their monotonicity, from the Monotonicity Types paper
HTML
1
star
85

RUG-WebEngineering-Elm

Presentation + Sample project for the Elm (and Sass) tutorial.
JavaScript
1
star