Mathematical helper functions for number formatting and Localize subsystems.
Provides arithmetic operations (add, subtract, multiply, divide), modulo, rounding (to arbitrary precision with selectable rounding modes), logarithms, powers, roots, square roots, significant-digit rounding, coefficient/exponent decomposition, and float-to-rational conversion.
All arithmetic operations accept integers, floats, and Decimals and return the most appropriate type.
Summary
Functions
Adds two numbers together.
Returns the adjusted modulus of x and y.
Calculates the error between a float and a rational approximation.
Returns a tuple representing a number in normalized form with
the mantissa in the range 0 < m < 10 and a base 10 exponent.
Returns a tuple representing a number in normalized form with
the mantissa as a Digits.t tuple and a base 10 exponent.
Calculates convergents (rational approximations) from continued fraction coefficients.
Returns the default number of rounding digits.
Returns the default rounding mode for rounding operations.
Divides one number by another.
Returns the adjusted quotient and remainder of two integers.
Returns the quotient and remainder of two integers.
Converts a float to a rational number {numerator, denominator}.
Returns the log base 10 of a number.
Returns the natural log of a number.
Converts a Decimal to an integer if possible, otherwise returns the value unchanged.
Calculates the modulo of a number (integer, float, or Decimal).
Multiplies two numbers together.
Raises one number to an exponent.
Raises a number to an integer power.
Returns 10 raised to the given power.
Calculates the nth root of a number.
Rounds a number to an arbitrary precision using one of several rounding algorithms.
Rounds a number to a specified number of significant digits.
Returns the list of valid rounding modes.
Calculates the square root of a Decimal number using Newton's method.
Subtracts one number from another.
Convert a Decimal to a float.
Check if a number is within a range.
Types
Functions
@spec add(number_or_decimal(), number_or_decimal()) :: number_or_decimal()
Adds two numbers together.
The numbers can be integers, floats, or Decimals. If either argument is a Decimal the result will be a Decimal. If both arguments are integers the result is an integer; if either is a float the result is a float.
Arguments
number_1is an integer, float, or Decimal.number_2is an integer, float, or Decimal.
Returns
- The sum of the two numbers.
Examples
iex> Localize.Utils.Math.add(1, 2)
3
iex> Localize.Utils.Math.add(Decimal.new("1.5"), 2)
Decimal.new("3.5")
@spec amod(number_or_decimal(), number_or_decimal()) :: number_or_decimal()
Returns the adjusted modulus of x and y.
If the modulo result is zero, returns y instead.
Arguments
xis an integer, float, or Decimal.yis an integer, float, or Decimal.
Returns
- The adjusted modulo result.
Examples
iex> Localize.Utils.Math.amod(10, 5)
5
iex> Localize.Utils.Math.amod(7, 3)
1
Calculates the error between a float and a rational approximation.
Arguments
originalis the original float.{numerator, denominator}is the approximate ratio.
Returns
- The absolute error as a float.
Examples
iex> Localize.Utils.Math.approximation_error(0.75, {3, 4})
0.0
@spec coef_exponent(number_or_decimal()) :: {number_or_decimal(), integer()}
Returns a tuple representing a number in normalized form with
the mantissa in the range 0 < m < 10 and a base 10 exponent.
Arguments
numberis an integer, float, or Decimal.
Returns
- A tuple
{mantissa, exponent}where the mantissa is in the range0 < m < 10.
Examples
iex> Localize.Utils.Math.coef_exponent(Decimal.new(465))
{Decimal.new("4.65"), 2}
@spec coef_exponent_digits(number_or_decimal()) :: {Localize.Utils.Digits.t(), integer()}
Returns a tuple representing a number in normalized form with
the mantissa as a Digits.t tuple and a base 10 exponent.
Arguments
numberis an integer, float, or Decimal.
Returns
- A tuple
{digits_tuple, exponent}wheredigits_tupleis of the form{digit_list, place, sign}.
Calculates convergents (rational approximations) from continued fraction coefficients.
Arguments
coefficientsis a list of continued fraction coefficients.
Returns
- A list of
{numerator, denominator}tuples.
Examples
iex> Localize.Utils.Math.convergents([3, 7, 15, 1])
[{333, 106}, {355, 113}, {22, 7}, {333, 106}, {3, 1}, {22, 7}]
@spec default_rounding() :: 3
Returns the default number of rounding digits.
Returns
- An integer (
3).
Examples
iex> Localize.Utils.Math.default_rounding()
3
@spec default_rounding_mode() :: :half_even
Returns the default rounding mode for rounding operations.
Returns
- The atom
:half_even.
Examples
iex> Localize.Utils.Math.default_rounding_mode()
:half_even
@spec div(number_or_decimal(), number_or_decimal()) :: Decimal.t()
Divides one number by another.
The numbers can be integers, floats, or Decimals. If either argument is a Decimal the result will be a Decimal. If both arguments are plain numbers the result will be a Decimal.
Arguments
number_1is an integer, float, or Decimal.number_2is an integer, float, or Decimal.
Returns
- The quotient of the two numbers as a Decimal.
Examples
iex> Localize.Utils.Math.div(Decimal.new(10), 2)
Decimal.new("5")
Returns the adjusted quotient and remainder of two integers.
This version returns the divisor if the remainder would otherwise be zero, and decrements the quotient by one.
Arguments
integer_1is an integer.integer_2is an integer.
Returns
- A tuple
{quotient, adjusted_remainder}.
Examples
iex> Localize.Utils.Math.div_amod(10, 5)
{1, 5}
iex> Localize.Utils.Math.div_amod(7, 3)
{2, 1}
Returns the quotient and remainder of two integers.
Arguments
integer_1is an integer.integer_2is an integer.
Returns
- A tuple
{quotient, remainder}.
Examples
iex> Localize.Utils.Math.div_mod(7, 3)
{2, 1}
Converts a float to a rational number {numerator, denominator}.
Arguments
xis any float.optionsis a keyword list of options.
Options
:max_iterations- Maximum number of continued fraction terms (default: 20).:epsilon- Tolerance for float comparisons (default: 1.0e-10).:max_denominator- Maximum allowed denominator (default: nil, meaning no limit).
Returns
- A tuple
{numerator, denominator}.
Examples
iex> Localize.Utils.Math.float_to_ratio(0.75)
{3, 4}
iex> Localize.Utils.Math.float_to_ratio(3.14159, max_iterations: 5)
{9208, 2931}
iex> Localize.Utils.Math.float_to_ratio(3.14159, max_denominator: 10)
{22, 7}
@spec log10(number_or_decimal()) :: float() | Decimal.t()
Returns the log base 10 of a number.
For integers and floats it calls the BIF :math.log10/1 function.
For Decimals the identity log10(x) = ln(x) / ln(10) is used.
Arguments
numberis an integer, float, or Decimal.
Returns
- The base-10 logarithm of the number.
Examples
iex> Localize.Utils.Math.log10(100)
2.0
iex> Localize.Utils.Math.log10(123)
2.089905111439398
iex> Localize.Utils.Math.log10(Decimal.new(9000))
Decimal.new("3.953767554157656512064441441")
Returns the natural log of a number.
For integers and floats it calls the BIF :math.log/1 function.
For Decimals the log is computed using a series expansion.
Arguments
numberis an integer, float, or Decimal.
Returns
- The natural logarithm of the number.
Examples
iex> Localize.Utils.Math.log(123)
4.812184355372417
iex> Localize.Utils.Math.log(Decimal.new(9000))
Decimal.new("9.103886231350952380952380952")
Converts a Decimal to an integer if possible, otherwise returns the value unchanged.
Arguments
numberis a Decimal, float, or integer.
Returns
An integer if the number has no fractional part.
The original value otherwise.
Examples
iex> Localize.Utils.Math.maybe_integer(Decimal.new("3.0"))
3
iex> Localize.Utils.Math.maybe_integer(2.0)
2
iex> Localize.Utils.Math.maybe_integer(5)
5
@spec mod(number_or_decimal(), number_or_decimal()) :: number_or_decimal()
Calculates the modulo of a number (integer, float, or Decimal).
Uses floored division rather than truncated division. This matches the semantics required by the CLDR plural rules specification.
Arguments
numberis an integer, float, or Decimal.modulusis an integer, float, or Decimal.
Returns
- The modulo result in the same type as the input.
Examples
iex> Localize.Utils.Math.mod(1234.0, 5)
4.0
iex> Localize.Utils.Math.mod(7, 3)
1
@spec mult(number_or_decimal(), number_or_decimal()) :: number_or_decimal()
Multiplies two numbers together.
The numbers can be integers, floats, or Decimals. If either argument is a Decimal the result will be a Decimal. If both arguments are integers the result is an integer; if either is a float the result is a float.
Arguments
number_1is an integer, float, or Decimal.number_2is an integer, float, or Decimal.
Returns
- The product of the two numbers.
Examples
iex> Localize.Utils.Math.mult(3, 4)
12
iex> Localize.Utils.Math.mult(Decimal.new("1.5"), 2)
Decimal.new("3.0")
Raises one number to an exponent.
Delegates to power/2.
Arguments
nis the base number.mis the exponent.
Returns
- The result of
nraised to the powerm.
@spec power(number_or_decimal(), number_or_decimal()) :: number_or_decimal()
Raises a number to an integer power.
Uses the binary exponentiation method. For Decimal numbers raising 10 to a power, the exponent is shifted directly for efficiency.
Arguments
numberis an integer, float, or Decimal.nis an integer exponent (or Decimal integer).
Returns
- The number raised to the given power.
Examples
iex> Localize.Utils.Math.power(10, 2)
100
iex> Localize.Utils.Math.power(10, 3)
1000
iex> Localize.Utils.Math.power(2, 10)
1024
Returns 10 raised to the given power.
Powers 0 through 326 are precomputed for efficiency. Negative powers return the reciprocal.
Arguments
nis an integer exponent.
Returns
An integer for non-negative exponents.
A float for negative exponents.
Examples
iex> Localize.Utils.Math.power_of_10(0)
1
iex> Localize.Utils.Math.power_of_10(3)
1000
iex> Localize.Utils.Math.power_of_10(-1)
0.1
Calculates the nth root of a number.
Arguments
numberis an integer or a Decimal.nthis a positive integer.
Returns
- The nth root of the number.
Examples
iex> Localize.Utils.Math.root(Decimal.new(8), 3)
Decimal.new("2.0")
iex> Localize.Utils.Math.root(Decimal.new(27), 3)
Decimal.new("3.0")
Rounds a number to an arbitrary precision using one of several rounding algorithms.
Rounding algorithms are based on the definitions given in IEEE 754, but also include two additional options.
Arguments
numberis a float, integer, or Decimal.placesis an integer number of decimal places to round to. Default is0.modeis the rounding mode to be applied. Default is:half_even.
Rounding modes
Directed roundings:
:down- Round towards 0 (truncate).:up- Round away from 0.:ceiling- Round toward positive infinity.:floor- Round toward negative infinity.
Round to nearest:
:half_even- Round to nearest value; tiebreak rounds towards the nearest even value. This is the default for IEEE binary floating-point.:half_up- Round to nearest value; tiebreak rounds away from 0.:half_down- Round to nearest value; tiebreak rounds towards 0.
Returns
- The rounded number.
Examples
iex> Localize.Utils.Math.round(1.5, 0, :half_even)
2.0
@spec round_significant(number_or_decimal(), integer()) :: number_or_decimal()
Rounds a number to a specified number of significant digits.
This is not the same as rounding fractional digits which is performed
by Decimal.round/2 and Float.round/2.
Arguments
numberis a float, integer, or Decimal.nis the number of significant digits to which thenumbershould be rounded.
Returns
- The number rounded to
nsignificant digits.
Examples
iex> Localize.Utils.Math.round_significant(3.14159, 3)
3.14
iex> Localize.Utils.Math.round_significant(10.3554, 1)
10.0
iex> Localize.Utils.Math.round_significant(0.00035, 1)
0.0004
Returns the list of valid rounding modes.
Returns
- A list of rounding mode atoms.
Calculates the square root of a Decimal number using Newton's method.
For integers and floats, delegates to the erlang :math module.
For Decimals, an initial estimate from :math.sqrt is refined
iteratively.
Arguments
numberis an integer, float, or Decimal.precisionis the desired precision (default: 0.0001).
Returns
- The square root of the number.
Examples
iex> Localize.Utils.Math.sqrt(Decimal.new(9))
Decimal.new("3.0")
iex> Localize.Utils.Math.sqrt(Decimal.new("9.869"))
Decimal.new("3.141496458696078173887197038")
@spec sub(number_or_decimal(), number_or_decimal()) :: number_or_decimal()
Subtracts one number from another.
The numbers can be integers, floats, or Decimals. If either argument is a Decimal the result will be a Decimal. If both arguments are integers the result is an integer; if either is a float the result is a float.
Arguments
number_1is an integer, float, or Decimal.number_2is an integer, float, or Decimal.
Returns
- The difference of the two numbers.
Examples
iex> Localize.Utils.Math.sub(5, 3)
2
iex> Localize.Utils.Math.sub(Decimal.new("5.5"), 3)
Decimal.new("2.5")
Convert a Decimal to a float.
Note that this conversion may lose precision for numbers that cannot be exactly represented as IEEE 754 floats.
Arguments
decimalis a%Decimal{}struct.
Returns
- A float value.
Examples
iex> Localize.Utils.Math.to_float(Decimal.new("1.5"))
1.5
Check if a number is within a range.
For integers the comparison uses the standard in operator.
For floats the comparison checks that the float has no
fractional part and falls within the range endpoints.
Arguments
numberis an integer or float.rangeis an ElixirRange.
Returns
trueif the number is within the range.falseotherwise.
Examples
iex> Localize.Utils.Math.within(2, 1..3)
true
iex> Localize.Utils.Math.within(2.0, 1..3)
true
iex> Localize.Utils.Math.within(2.1, 1..3)
false