chunky v0.13.0 Chunky.Fraction View Source

Functions for creating and manipulating fractions.

Most functions will work with combinations of Fractions and Integers. All of the fraction functions work with explicit integer numerators and denominators, falling back to returning floating point number only when configured to in special circumstances.

Value Coercion

A subset of functions for working with fractions will automatically coerce things that look like fractions - any value that can be parsed by some version of new/1. This includes:

  • Existing fractions %Fraction{num: 22, den:7}
  • Integers 14
  • Floats 1.75
  • 2-tuples {3, 91}
  • Integer as String "4"
  • Float as String "1.35"
  • Fraction as String "2/9"

See new/1 for more information about how values are converted to fractions.

The following functions support mixed types as parameters, either positionally (like the basic math functions) or as part of a list (aggregate functions):

Creating Fractions

Construct fractions from a single integer, tuple of integers, or a pair of integer parameters.

  • new/1 - Create a Fraction from an integer, float, string, or tuple of integers
  • new/2 - Create a Fraction from a numerator and denominator, or a float with options
iex> Fraction.new(3)
%Fraction{num: 3, den: 1}

iex> Fraction.new({22, 7})
%Fraction{num: 22, den: 7}

iex> Fraction.new(0.25, conversion: :precision)
%Fraction{num: 1, den: 4}

iex> Fraction.new("-33/913")
%Fraction{num: -33, den: 913}

iex> Fraction.new(5, 11)
%Fraction{num: 5, den: 11}

Basic Math

Standard math functions that work with two fractions, or a fraction and an integer. Options allow for automatic simplification and control over how certain operations work.

  • absolute_value/1 - Absolute value |v| of fraction
  • add/3 - Add two fractions, or a fraction and a value compatible with new/1
  • ceiling/1 - Round a fraction up to the nearest whole value
  • decrement/2 - Decrement the numerator or denominator by one
  • divide/3 - Divide two fractions, or a fraction and a value compatible with new/1
  • floor/1 - Round a fraction down to the nearest whole value
  • increment/2 - Increment the numerator or denominator by one
  • max_of/2 - Find the larger of two fractions, or a fraction and a value compatible with new/1
  • min_of/2 - Find the smaller of two fractions, or a fraction and value compatible with new/1
  • multiply/3 - Multiply two fractions, or a fraction and a value compatible with new/1
  • power/3 - Take a fraction or an integer to the power of a fraction or an integer
  • round/1 - Round to the nearest whole value
  • subtract/3 - Subtract two fractions, or a fraction and a value compatible with new/1
iex> Fraction.new(4, 3) |> Fraction.add(Fraction.new({1, 6})) |> Fraction.power(2)
%Fraction{num: 81, den: 36}

iex> Fraction.power(8, Fraction.new(1, 3))
%Fraction{num: 2, den: 1}

Comparisons

Binary comparisons between two fractions or a fraction and an integer.

  • eq?/2 - Equality (==) comparison between two fractions, or a fraction and an integer
  • gt?/2 - Greater than (>) comparison between two fractions, or a fraction and an integer
  • gte?/2 - Greater than or equal (>=) comparison between two fractions, or a fraction and an integer
  • lt?/2 - Less than (<) comparison between two fractions, or a fraction and an integer
  • lte?/2 - Less than or equal (<=) comparison between two fractions, or a fraction and an integer
  • near_equal?/3 - Test if the difference between two fractions is less than or equal to another fraction
  • within?/2 - Test if a fraction is within the specified Range
  • within?/3 - Test if a fraction is within the lower and upper value bounds
iex> Fraction.gt?(Fraction.new(7, 8), Fraction.new(8, 9))
false

iex> Fraction.eq?(3, Fraction.new(27, 9))
true

Fraction Manipulation

Manipulate the components of individual fractions.

  • components/1 - Get the numerator and denominator of a fraction as a tuple of integers
  • get_remainder/1 - Get fractional remainder after removing all whole values of a fraction
  • get_whole/1 - Get whole value portion of a fraction
  • reciprocal/2 - Inverse or reciprocal of a fraction
  • simplify/1 - Simplify a fraction to it's reduced form
  • split/1 - Extract the whole value portion and the remainer portion of a fraction as a tuple
  • to_float/2 - Convert a fraction to a floating point value
iex> Fraction.new(88, 28) |> Fraction.simplify() |> Fraction.split()
{3, %Fraction{num: 1, den: 7}}

iex> Fraction.new(22, 7) |> Fraction.to_float(precision: 2)
3.14

Aggregate Functions

Work with multiple fractions in aggregate. Most aggregate functions will work with Fractions, or any value that can be converted to a fraction with new/1.

  • clamp/2 - Constrain a list of values to be within a specific range
  • fractionalize/1 - Convert a list of fraction representations (anything that works with new/1) into Fraction structs
  • max_of/1 - Find the largest value in a list of fractions, or literals compatible with new/1
  • min_of/1 - Find the smallest value in a list of fractions, or literals compatible with new/1
  • min_max_of/1 - Find the smallest and largest values in a list of fractions or literals compatible with new/1
  • normalize/2 - Convert two fractions to a common denominator
  • normalize_all/1 - Convert a list of two or more fractions to a common denominator
  • sort/2 - Sort a list of values as fractions
  • sum/2 - Find the sum of a list of fractions
  • uniq/2 - Extract unique fractions from a list of values
iex> Fraction.normalize(Fraction.new(22, 7), Fraction.new(4, 3))
{ %Fraction{num: 66, den: 21}, %Fraction{num: 28, den: 21} }

iex> Fraction.max_of(["3/4", {4, 5}, 1.5])
%Fraction{num: 15, den: 10}

Inspection

Inspect the properties of individual fractions.

iex> Fraction.new(3, 18) |> is_simplified?()
false

Link to this section Summary

Functions

Get the absolute value of a fraction.

Add two fractions, or a fraction and a value, and return the (optionally simplified) result.

Find the ceiling of a fractional value.

Constrain a list of values as fraction to only those values within the specified min and max.

Extract the numerator and denominator of a fraction as a tuple of values.

Decrement the numerator or denominator by one.

Divide two fractions, or a fraction and a value and return the (optionally simplified) result.

Compare a fraction with a value or fraction using equals comparison.

Find the floor of a fractional value.

Take a mixed list of fraction representations %Fraction{}, integer, float, string, etc), and convert all to fractions. This is not a normalization process - the resulting fractions are not guaranteed to share a denominator.

Get the fractional part left after removing any whole components from the fraction.

Get the whole component of a fraction.

Compare a fraction with a value or fraction using greater than comparison.

Compare a fraction with a value or fraction using greater than or equal comparison.

Determine if a fraction is greater than 1, and has a whole number component.

Increment the numerator or denominator by one.

Determine if a fraction is negative.

Determine if a fraction is positive.

Determine if a fraction is in simplified form.

Determine if a fraction exactly represents a whole number, with no remainder.

Does a fraction represent a zero value?

Compare a fraction with a value or fraction using less than comparison.

Compare a fraction with a value or fraction using less than or equal comparison.

Return the maximum value in a list of fractions or values. Relative comparisons are calculated based on float converion of fractions.

Return the larger of two fractions or values.

Return a tuple with the smallest and largest fractions from a list.

Find the minimum value in a list of fractions or vaules. Relative comparisons are calculated based on float conversion of fractions.

Return the smaller of two fractions, or a fraction and an alternate encoding (like float, string, or integer).

Multiply two fractions, or a fraction and a value and return the (optionally simplified) result.

Determine if two fractions close enough in value.

Convert a string encoding of an integer, float, or fraction into a fraction.

Convert a floating point value to a fraction.

Change a combination of fractions, or fractions and integers, into the same denominator.

Normalize (move to the same denominator) all of the fractions and integers in a list.

Use fractions in power/exponent calculations.

Create the reciprocal of a fraction, optionally simplifying the result.

Round a fraction to the nearest whole value.

Simplify a fraction.

Sort a list of values.

Break a fraction into whole and fractional parts, returning both.

Subtract two fractions, or a fraction an a value, and return the (optionally) simplified result.

Add a series of fractions and integers.

Convert a fraction to a float, optionally rounding to a specific precision.

Return only the unique fractions from a list of values.

Determine if a fraction falls within a specific range.

Determine if a fraction falls within a specified lower and upper bound.

Link to this section Functions

Get the absolute value of a fraction.

Supports Type Coercion?: ✅

Examples

iex> Fraction.new("-34/9") |> Fraction.absolute_value()
%Fraction{num: 34, den: 9}

iex> Fraction.absolute_value("-44/7")
%Fraction{num: 44, den: 7}
Link to this function

add(value_a, value_b, opts \\ [])

View Source

Add two fractions, or a fraction and a value, and return the (optionally simplified) result.

Supports Type Coercion?: ✅

Options

  • simplify - Boolean - default false. Return result as a simplified fraction.

Examples

iex> Fraction.add(Fraction.new(1, 2), Fraction.new(-8, 3))
%Fraction{num: -13, den: 6}

iex> Fraction.add(Fraction.new(3, 4), Fraction.new(3, 4), simplify: true)
%Fraction{num: 3, den: 2}

iex> Fraction.add(Fraction.new(1, 3), 5)
%Fraction{num: 16, den: 3}

iex> Fraction.add(2, Fraction.new(5, 4))
%Fraction{num: 13, den: 4}

iex> Fraction.add("2/3", Fraction.new(5, 3))
%Fraction{num: 7, den: 3}

Find the ceiling of a fractional value.

The ceiling of n, or ⌈n⌉, rounds a fractional value up to the nearest whole value.

Supports Type Coercion?: ✅

Examples

iex> Fraction.new("7/8") |> Fraction.ceiling()
%Fraction{num: 8, den: 8}

iex> Fraction.new("0/17") |> Fraction.ceiling()
%Fraction{num: 0, den: 17}

iex> Fraction.new("-47/3") |> Fraction.ceiling()
%Fraction{num: -45, den: 3}

iex> Fraction.ceiling(-3.5)
%Fraction{num: -30, den: 10}
Link to this function

clamp(values, opts \\ [])

View Source

Constrain a list of values as fraction to only those values within the specified min and max.

Values that are not yet Fractions are coerced into fractional values before processing.

Supports Type Coercion?: ✅

Options

  • min - Minimum value for constraining value list. Can be any value that is handled by new/1
  • max - Maximum value for constraining value list. Can be any value that is handled by new/1
  • min_inclusive - Boolean. Default true. Use inclusive minimum constraint (values >= min), otherwise use exclusive (values > min).
  • max_inclusive - Boolean. Default true. Use inclusive maximum constraint (values <= max), otherwise use exclusive (values < max).

Examples

iex> Fraction.clamp(["22/7", "14/7", "11/7", "7/7"], min: 1, max: 2, inclusive_max: false)
[%Fraction{num: 11, den: 7}, %Fraction{num: 7, den: 7}]

iex> Fraction.clamp(["22/7", "14/7", "11/7", "7/7"], min: 1, max: 2, inclusive_min: false)
[%Fraction{num: 14, den: 7}, %Fraction{num: 11, den: 7}]

Extract the numerator and denominator of a fraction as a tuple of values.

Examples

iex> Fraction.new(1, 37) |> Fraction.components()
{1, 37}

iex> Fraction.new(0, 3) |> Fraction.components()
{0, 3}
Link to this function

decrement(fraction, mode)

View Source

Decrement the numerator or denominator by one.

This is not necessarily an arithmatically valid operation, rather it directly decrements the numerator or denominator. If the decrement would create an invalid denominator, it will return an error instead.

Valid mode values are: :both, :num, :numerator, :den, or :denominator. Note that when decrementing a negative value by the numerator, the value will move away from 0, towards the negative.

Examples

iex> Fraction.new("7/11") |> Fraction.decrement(:num)
%Fraction{num: 6, den: 11}

iex> Fraction.new("-5/9") |> Fraction.decrement(:den)
%Fraction{num: -5, den: 8}

iex> Fraction.new("-7/3") |> Fraction.decrement(:numerator)
%Fraction{num: -8, den: 3}

iex> Fraction.new("47/1") |> Fraction.decrement(:denominator)
{:error, :invalid_denominator}

iex> Fraction.new("-21/4") |> Fraction.decrement(:both)
%Fraction{num: -22, den: 3}
Link to this function

divide(value_a, value_b, opts \\ [])

View Source

Divide two fractions, or a fraction and a value and return the (optionally simplified) result.

Supports Type Coercion?: ✅

Options

  • simplify - Boolean - default false. Return result as a simplified fraction.

Examples

iex> Fraction.divide(Fraction.new(3, 4), Fraction.new(-7, 2))
%Fraction{num: -6, den: 28}

iex> Fraction.divide(Fraction.new(28, 4), 4, simplify: true)
%Fraction{num: 7, den: 4}

iex> Fraction.divide(60, Fraction.new(7, 12))
%Fraction{num: 720, den: 7}

iex> Fraction.divide(Fraction.new(11, 17), "3")
%Fraction{num: 11, den: 51}
Link to this function

eq?(fraction_a, fraction_b)

View Source

Compare a fraction with a value or fraction using equals comparison.

Supports Type Coercion?: ✅

Examples

iex> Fraction.eq?(Fraction.new(7, 9), Fraction.new(3, 5))
false

iex> Fraction.eq?(3, Fraction.new(12, 4))
true

iex> Fraction.eq?(Fraction.new(-3, 12), -2)
false

Find the floor of a fractional value.

The floor of n, or ⌊n⌋, rounds a fractional value down to the nearest whole value.

Supports Type Coercion?: ✅

Examples

iex> Fraction.new("17/8") |> Fraction.floor()
%Fraction{num: 16, den: 8}

iex> Fraction.new("3/5") |> Fraction.floor()
%Fraction{num: 0, den: 5}

iex> Fraction.new("-17/9") |> Fraction.floor()
%Fraction{num: -18, den: 9}

iex> Fraction.floor("31/8")
%Fraction{num: 24, den: 8}
Link to this function

fractionalize(candidates)

View Source

Take a mixed list of fraction representations %Fraction{}, integer, float, string, etc), and convert all to fractions. This is not a normalization process - the resulting fractions are not guaranteed to share a denominator.

Supports Type Coercion?: ✅

Example

iex> fractionalize([%Fraction{num: 3, den: 4}, 12, 0.25, "22/7", "4"])
[%Fraction{num: 3, den: 4}, %Fraction{num: 12, den: 1}, %Fraction{num: 25, den: 100}, %Fraction{num: 22, den: 7}, %Fraction{num: 4, den: 1}]

Get the fractional part left after removing any whole components from the fraction.

Example

iex> Fraction.new(3, 45) |> Fraction.get_remainder()
%Fraction{num: 3, den: 45}

iex> Fraction.new(7, 3) |> Fraction.get_remainder()
%Fraction{num: 1, den: 3}

iex> Fraction.new(-10, 4) |> Fraction.get_remainder()
%Fraction{num: -2, den: 4}

Get the whole component of a fraction.

Examples

iex> Fraction.new(3, 7) |> Fraction.get_whole()
0

iex> Fraction.new(22, 7) |> Fraction.get_whole()
3

iex> Fraction.new(-10, 2) |> Fraction.get_whole()
-5
Link to this function

gt?(fraction_a, fraction_b)

View Source

Compare a fraction with a value or fraction using greater than comparison.

Supports Type Coercion?: ✅

Examples

iex> Fraction.gt?(Fraction.new(7, 9), Fraction.new(3, 5))
true

iex> Fraction.gt?(3, Fraction.new(15, 4))
false

iex> Fraction.gt?(Fraction.new(-3, 12), -2)
true
Link to this function

gte?(fraction_a, fraction_b)

View Source

Compare a fraction with a value or fraction using greater than or equal comparison.

Supports Type Coercion?: ✅

Examples

iex> Fraction.gte?(Fraction.new(3, 9), Fraction.new(1, 3))
true

iex> Fraction.gte?(3, Fraction.new(15, 4))
false

iex> Fraction.gte?(Fraction.new(-3, 12), -2)
true

Determine if a fraction is greater than 1, and has a whole number component.

Examples

iex> Fraction.new(3, 17) |> Fraction.has_whole?()
false

iex> Fraction.new(22, 7) |> Fraction.has_whole?()
true
Link to this function

increment(fraction, mode)

View Source

Increment the numerator or denominator by one.

This is not necessarily an arithmatically valid operation, rather it directly increments the numerator or denominator.

Valid mode values are: :both, :num, :numerator, :den, or :denominator. Note that when incrementing a negative value by the numerator, the value will move towards 0, not towards the negative.

Examples

iex> Fraction.new("7/11") |> Fraction.increment(:num)
%Fraction{num: 8, den: 11}

iex> Fraction.new("-5/9") |> Fraction.increment(:den)
%Fraction{num: -5, den: 10}

iex> Fraction.new("-7/3") |> Fraction.increment(:numerator)
%Fraction{num: -6, den: 3}

iex> Fraction.new("21/6") |> Fraction.increment(:both)
%Fraction{num: 22, den: 7}
Link to this macro

is_coercible?(value)

View Source (macro)

Determine if a fraction is negative.

Examples

iex> Fraction.new(-3, 4) |> Fraction.is_negative?()
true

Determine if a fraction is positive.

Examples

iex> Fraction.new(-3, 4) |> Fraction.is_positive?()
false
Link to this function

is_simplified?(fraction)

View Source

Determine if a fraction is in simplified form.

Examples

iex> Fraction.new(2, 4) |> Fraction.is_simplified?()
false

iex> Fraction.new(-10, 4) |> Fraction.is_simplified?()
false

iex> Fraction.new(0, 7) |> Fraction.is_simplified?()
false

iex> Fraction.new(22, 7) |> Fraction.is_simplified?()
true

Determine if a fraction exactly represents a whole number, with no remainder.

Examples

iex> Fraction.new(5, 3) |> Fraction.is_whole?()
false

iex> Fraction.new(-22, 11) |> Fraction.is_whole?()
true

Does a fraction represent a zero value?

Examples

iex> Fraction.new(3, 134) |> Fraction.is_zero?()
false

iex> Fraction.new(0, 34) |> Fraction.is_zero?()
true
Link to this function

lt?(fraction_a, fraction_b)

View Source

Compare a fraction with a value or fraction using less than comparison.

Supports Type Coercion?: ✅

Examples

iex> Fraction.lt?(Fraction.new(7, 9), Fraction.new(3, 5))
false

iex> Fraction.lt?(3, Fraction.new(15, 4))
true

iex> Fraction.lt?(Fraction.new(-3, 12), -2)
false
Link to this function

lte?(fraction_a, fraction_b)

View Source

Compare a fraction with a value or fraction using less than or equal comparison.

Supports Type Coercion?: ✅

Examples

iex> Fraction.lte?(Fraction.new(7, 9), Fraction.new(3, 5))
false

iex> Fraction.lte?(3, Fraction.new(15, 4))
true

iex> Fraction.lte?(Fraction.new(-24, 12), -2)
true

Return the maximum value in a list of fractions or values. Relative comparisons are calculated based on float converion of fractions.

Supports Type Coercion?: ✅

Example

iex> Fraction.max_of([ Fraction.new(3, 7), Fraction.new(5, 11), Fraction.new(11, 23)])
%Fraction{num: 11, den: 23}
Link to this function

max_of(fraction_a, fraction_b)

View Source

Return the larger of two fractions or values.

Supports Type Coercion?: ✅

Example

iex> Fraction.max_of( Fraction.new(3, 7), Fraction.new(11, 28) )
%Fraction{num: 3, den: 7}

iex> Fraction.max_of(Fraction.new(4, 3), 8.3)
%Fraction{num: 83, den: 10}

Return a tuple with the smallest and largest fractions from a list.

Supports Type Coercion?: ✅

Example

iex> Fraction.min_max_of([ Fraction.new(3, 7), Fraction.new(5, 11), Fraction.new(11, 23)])
{ %Fraction{num: 3, den: 7}, %Fraction{num: 11, den: 23} }

Find the minimum value in a list of fractions or vaules. Relative comparisons are calculated based on float conversion of fractions.

Supports Type Coercion?: ✅

Example

iex> Fraction.min_of([ Fraction.new(3, 7), Fraction.new(5, 11), Fraction.new(11, 23)])
%Fraction{num: 3, den: 7}
Link to this function

min_of(fraction_a, fraction_b)

View Source

Return the smaller of two fractions, or a fraction and an alternate encoding (like float, string, or integer).

Supports Type Coercion?: ✅

Example

iex> Fraction.min_of( Fraction.new(3, 7), Fraction.new(11, 28) )
%Fraction{num: 11, den: 28}

iex> Fraction.min_of( Fraction.new(22, 7), "3/7")
%Fraction{num: 3, den: 7}

iex> Fraction.min_of(0.5, Fraction.new(-3, 5))
%Fraction{num: -3, den: 5}

iex> Fraction.min_of(Fraction.new(3), "22/7")
%Fraction{num: 3, den: 1}
Link to this function

multiply(value_a, value_b, opts \\ [])

View Source

Multiply two fractions, or a fraction and a value and return the (optionally simplified) result.

Supports Type Coercion?: ✅

Options

  • simplify - Boolean - default false. Return result as a simplified fraction.

Examples

 iex> Fraction.multiply(Fraction.new(3, 7), Fraction.new(22, 7))
 %Fraction{num: 66, den: 49}

 iex> Fraction.multiply(Fraction.new(2, 9), 33, simplify: true)
 %Fraction{num: 22, den: 3}

 iex> Fraction.multiply(4, Fraction.new(12, 5))
 %Fraction{num: 48, den: 5}

 iex> Fraction.multiply("4", Fraction.new(22, 7))
 %Fraction{num: 88, den: 7}
Link to this function

near_equal?(fraction_a, fraction_b, fraction_epsilon)

View Source

Determine if two fractions close enough in value.

This is similar to doing floating point comparison, where an epsilon value is used to determine if two values are within a given range of each other.

In this case, we test if the difference between the first two fractions is less than or equal to the third fraction. So, if we wanted to determine if 3/2 and 5/3 were within 1/4 of each other, or had a difference less than or equal to 1/4:

  iex> Fraction.near_equal?("3/2", "5/3", "1/4") 
  true

Examples

  iex> Fraction.near_equal?("1/10", "8/10", 0.05)
  false

  iex> Fraction.near_equal?("-1/3", "4/3", 2)
  true

Convert a string encoding of an integer, float, or fraction into a fraction.

Example

iex> Fraction.new("3")
%Fraction{num: 3, den: 1}

iex> Fraction.new("12/7")
%Fraction{num: 12, den: 7}

iex> Fraction.new("13 / 5")
%Fraction{num: 13, den: 5}

iex> Fraction.new("foo/bar")
{:error, :no_parsable_fraction}

iex> Fraction.new("3.14")
%Fraction{num: 314, den: 100}

Convert a floating point value to a fraction.

There are two modes for converting values:

  • Using precision approximation (via Float.ratio/1)
  • Using natural conversion

Natural conversion tries to find a fraction that represents the intended value of a float, while precision approximation tries to find a fractional representation of the encoded floating point value. Use the conversion flag to toggle between the two modes.

Flags

  • conversion - Atom. One of :natural or :precision

Example

iex> Fraction.new(0.9, conversion: :natural) |> to_string()
"9/10"

iex> Fraction.new(0.9, conversion: :precision) |> to_string()
"8106479329266893/9007199254740992"

iex> Fraction.new(3.14, conversion: :natural) |> to_string()
"314/100"

iex> Fraction.new(3.14, conversion: :precision) |> to_string()
"7070651414971679/2251799813685248"
Link to this function

normalize(fraction_a, int)

View Source

Change a combination of fractions, or fractions and integers, into the same denominator.

Example

iex> Fraction.normalize(Fraction.new(3, 4), Fraction.new(1, 7))
{ %Fraction{num: 21, den: 28}, %Fraction{num: 4, den: 28} }

iex> Fraction.normalize(3, Fraction.new(2, 5))
{ %Fraction{num: 15, den: 5}, %Fraction{num: 2, den: 5} }

iex> Fraction.normalize(Fraction.new(6, 4), 2)
{ %Fraction{num: 6, den: 4}, %Fraction{num: 8, den: 4} }

Normalize (move to the same denominator) all of the fractions and integers in a list.

Supports Type Coercion?: ✅

Examples

 iex> Fraction.normalize_all([Fraction.new(1, 2), Fraction.new(2, 3), Fraction.new(3, 4), 7])
 [
     %Fraction{den: 12, num: 6},
     %Fraction{den: 12, num: 8},
     %Fraction{den: 12, num: 9},
     %Fraction{den: 12, num: 84}
 ]

 iex> Fraction.normalize_all(["3/4", {7, 8}, Fraction.new(8, 16)])
 [
      %Fraction{num: 12, den: 16},
      %Fraction{num: 14, den: 16},
      %Fraction{num: 8, den: 16}
 ]

Use fractions in power/exponent calculations.

The base or the power (or both) can be fractions.

Fractions taken to an integer power will behave as expected:

iex> Fraction.power(Fraction.new(3, 4), 7)
%Chunky.Fraction{den: 16384, num: 2187}

Fractions or integers taken to a fractional power will not always return expected values, as most fractional powers do not have a result that can be represented as a fraction. By default the power functions will return an error value in these cases:

iex> Fraction.power(9, Fraction.new(7, 13))
{:error, :no_fractional_power}

If you want the floating point fractional result, you can use the allow_irrational flag:

iex> Fraction.power(9, Fraction.new(7, 13), allow_irrational: true)
3.26454673038995

When calculating the fractional power of a value, an epsilon value is used as part of the n-th root finding and resulting analysis The epsilon determines how close to a whole number different components of the resulting fractions need to be, to be treated as whole numbers.

Options

  • simplify - Boolean. Default false. Optionally simplify the return fraction
  • epsilon - Float. Small number used to compare how close two values are
  • allow_irrational - Boolean. eDefault false. Allow a non-fractional (irrational) result to be returned

Examples

iex> Fraction.power(Fraction.new(7, 32), Fraction.new(30, 5))
%Fraction{num: 117649, den: 1073741824}

iex> Fraction.power(Fraction.new(3, 5), 3)
%Fraction{num: 27, den: 125}

iex> Fraction.power(4, Fraction.new(-4, 8))
%Fraction{num: 1, den: 2}

iex> Fraction.power(9, Fraction.new(7, 13), allow_irrational: true)
3.26454673038995

iex> Fraction.power("3/8", 2.0)
%Fraction{num: 9, den: 64}
Link to this function

reciprocal(fraction, opts \\ [])

View Source

Create the reciprocal of a fraction, optionally simplifying the result.

Negative fractions will switch the sign to carry on the new numerator. Trying to take the reciprocal of a zero fraction will result in an error.

Options

  • simplify - Boolean - default false. Return result as a simplified fraction.

Examples

iex> Fraction.new(3, 4) |> Fraction.reciprocal()
%Fraction{num: 4, den: 3}

iex> Fraction.new(-4, 40) |> Fraction.reciprocal(simplify: true)
%Fraction{num: -10, den: 1}

iex> Fraction.new(0, 3) |> Fraction.reciprocal()
{:error, :invalid_denominator}

Round a fraction to the nearest whole value.

This round function uses the "round half away from zero" strategy, which differs from standard IEEE-754 floating point rounding mode, as we don't lose precision as fractions grow. Using this round method avoids introducing even/odd bias over multiple calculations.

Supports Type Coercion?: ✅

Examples

iex> Fraction.round("22/7")
%Fraction{num: 21, den: 7}

iex> Fraction.round("-13/8")
%Fraction{num: -16, den: 8}

Simplify a fraction.

Examples

iex> Fraction.new(6, 8) |> Fraction.simplify()
%Fraction{num: 3, den: 4}

iex> Fraction.new(24, 8) |> Fraction.simplify()
%Fraction{num: 3, den: 1}

iex> Fraction.new(22, 7) |> Fraction.simplify()
%Fraction{num: 22, den: 7}
Link to this function

sort(values, opts \\ [])

View Source

Sort a list of values.

Values that are not yet Fractions are coerced into fractional values before processing.

Supports Type Coercion?: ✅

Sorting is done based on floating point values of fractions.

Options

  • sorter - Function arity 2. Default &<=/2. Comparison to use when sorting.

Examples

iex> Fraction.sort(["22/7", 3, "2.9", Fraction.new(1, 3)])
[%Fraction{num: 1, den: 3}, %Fraction{num: 29, den: 10}, %Fraction{num: 3, den: 1}, %Fraction{num: 22, den: 7}]

iex> Fraction.sort(["22/7", 3, "2.9", Fraction.new(1, 3)], sorter: &>=/2)
[%Fraction{num: 22, den: 7}, %Fraction{num: 3, den: 1}, %Fraction{num: 29, den: 10}, %Fraction{num: 1, den: 3}]

Break a fraction into whole and fractional parts, returning both.

Examples

iex> Fraction.new(6, 4) |> Fraction.split()
{1, %Fraction{num: 2, den: 4}}

iex> Fraction.new(-22, 7) |> Fraction.split()
{-3, %Fraction{num: -1, den: 7}}

iex> Fraction.new(0, 3) |> Fraction.split()
{0, %Fraction{num: 0, den: 3}}
Link to this function

subtract(value_a, value_b, opts \\ [])

View Source

Subtract two fractions, or a fraction an a value, and return the (optionally) simplified result.

Supports Type Coercion?: ✅

Options

  • simplify - Boolean - default false. Return result as a simplified fraction.

Examples

iex> Fraction.subtract(Fraction.new(3, 5), Fraction.new(1, 5))
%Fraction{num: 2, den: 5}

iex> Fraction.subtract(2, Fraction.new(-6, 9), simplify: true)
%Fraction{num: 8, den: 3}

iex> Fraction.subtract(Fraction.new(-2, 4), -5, simplify: true)
%Fraction{num: 9, den: 2}

iex> Fraction.subtract(Fraction.new(8, 10), 0.5)
%Fraction{num: 3, den: 10}

Add a series of fractions and integers.

Supports Type Coercion?: ✅

Options

  • simplify - Boolean - default false. Return result as a simplified fraction.

Example

iex> Fraction.sum([Fraction.new(3, 4), Fraction.new(5, 7), Fraction.new(8, 11), 1, Fraction.new(249, 308)])
%Fraction{num: 1232, den: 308}

iex> Fraction.sum([Fraction.new(3, 4), Fraction.new(5, 7), Fraction.new(8, 11), 1, Fraction.new(249, 308)], simplify: true)
%Fraction{num: 4, den: 1}
Link to this function

to_float(fraction, opts \\ [])

View Source

Convert a fraction to a float, optionally rounding to a specific precision.

Options

  • precision - Integer. Default 15. Number of digits of precision in float. From 0 to 15.

Examples

iex> Fraction.new(22, 7) |> to_float()
3.142857142857143

iex> Fraction.new(22, 7) |> to_float(precision: 2)
3.14
Link to this function

uniq(values, opts \\ [])

View Source

Return only the unique fractions from a list of values.

Values that are not yet Fractions are coerced into fractional values before processing.

Supports Type Coercion?: ✅

Determining what is unique from the list of values is controlled by the by option. By default, value comparison is used, so 1/2 and 2/4 would be equal, and only one returned. If components comparison is specified, the literal numerator and denominator must match, so non-simplified, but value equal fractions would be different from one another.

Options

  • by - Either :value or :components. Default :value.

Examples

iex> Fraction.uniq(["2/4", Fraction.new(4, 2), 2, 0.5])
[%Fraction{num: 2, den: 4}, %Fraction{num: 4, den: 2}]

iex> Fraction.uniq(["2/4", Fraction.new(4, 2), 2, 0.5], by: :components)
[%Fraction{num: 2, den: 4}, %Fraction{num: 4, den: 2}, %Fraction{num: 2, den: 1}, %Fraction{num: 5, den: 10}]
Link to this function

within?(fraction, range)

View Source

Determine if a fraction falls within a specific range.

Supports Type Coercion?: ✅

Examples

iex> Fraction.new("22/7") |> Fraction.within?(3..4)
true

iex> Fraction.new("3/5") |> Fraction.within?(-1..1)
true

iex> Fraction.within?(3.1, 1..5)
true
Link to this function

within?(fraction, low, hi)

View Source

Determine if a fraction falls within a specified lower and upper bound.

This test is inclusive of the lower and upper bounds. The low and high value of the range to test can be specified as any coercible value.

Supports Type Coercion?: ✅

Examples

iex> Fraction.new("22/7") |> Fraction.within?(3, 4.5)
true

iex> Fraction.new("-4/3") |> Fraction.within?("-10/3", "-4/3")
true

iex> Fraction.within?("22/7", -3, 4)
true