Decimal
Decimal arithmetic on arbitrary precision floatingpoint numbers.
A number is represented by a signed coefficient and exponent such that: `sign
 coefficient * 10^exponent`. All numbers are represented and calculated
exactly, but the result of an operation may be rounded depending on the
context the operation is performed with, see:
Decimal.Context
. Trailing zeros in the coefficient are never truncated to preserve the number of significant digits unless explicitly done so.
There are also special values such as NaN and (+)Infinity. 0 and +0 are two
distinct values. Some operations results are not defined and will return NaN.
This kind of NaN is quiet, any operation returning a number will return
NaN when given a quiet NaN (the NaN value will flow through all operations).
The other kind of NaN is signalling which is the value that can be reached
in Error.result/1
when the result is NaN. Any operation given a signalling
NaN return will signal :invalid_operation
.
Exceptional conditions are grouped into signals, each signal has a flag and a
trap enabler in the context. Whenever a signal is triggered it’s flag is set
in the context and will be set until explicitly cleared. If the signal is trap
enabled Decimal.Error
will be raised.
Specifications
This implementation follows the above standards as closely as possible. But at some places the implementation diverges from the specification. The reasons are different for each case but may be that the specification doesn’t map to this environment, ease of implementation or that API will be nicer. Still, the implementation is close enough that the specifications can be seen as additional documentation that can be used when things are unclear.
The specification models the sign of the number as 1, for a negative number, and 0 for a positive number. Internally this implementation models the sign as 1 or 1 such that the complete number will be: `sign coefficient 10^exponent` and will refer to the sign in documentation as either positive or negative.
There is currently no maximum or minimum values for the exponent. Because of that all numbers are “normal”. This means that when an operation should, according to the specification, return a number that “underflow” 0 is returned instead of Etiny. This may happen when dividing a number with infinity. Additionally, overflow, underflow and clamped may never be signalled.
Summary↑
abs(num)  The absolute value of given number. Sets the number’s sign to positive 
add(num1, decimal)  Adds two numbers together 
compare(num1, num2)  Compares two numbers numerically. If the first number is greater than the second

decimal?(decimal)  Returns 
div(num1, decimal)  Divides two numbers 
div_int(num1, num2)  Divides two numbers and returns the integer part 
div_rem(num1, decimal)  Integer division of two numbers and the remainder. Should be used when both

equal?(num1, num2)  Compares two numbers numerically and returns 
get_context()  Gets the process’ context 
inf?(decimal)  Returns 
max(decimal, num2)  Compares two values numerically and returns the maximum. Unlike most other
functions in 
min(decimal, num2)  Compares two values numerically and returns the minimum. Unlike most other
functions in 
minus(num)  Negates the given number 
mult(num1, decimal)  Multiplies two numbers 
nan?(decimal)  Returns 
new(num)  Creates a new decimal number from a string representation, an integer or a
floating point number. Floating point numbers will be converted to decimal
numbers with 
new(sign, coefficient, exponent)  Creates a new decimal number from the sign, coefficient and exponent such that
the number will be: 
plus(num)  Applies the context to the given number rounding it to specified precision 
reduce(num)  Reduces the given number. Removes trailing zeros from coefficient while keeping the number numerically equivalent by increasing the exponent 
rem(num1, num2)  Remainder of integer division of two numbers. The result will have the sign of the first number 
round(num, places \\ 0, mode \\ :half_up)  Rounds the given number to specified decimal places with the given strategy (default is to round to nearest one). If places is negative, at least that many digits to the left of the decimal point will be zero 
set_context(context)  Set the process’ context 
sub(num1, num2)  Subtracts second number from the first. Equivalent to 
to_string(num, type \\ :scientific)  Converts given number to its string representation 
update_context(fun)  Update the process’ context 
with_context(context, fun)  Runs function with given context 
Types ↑
signal :: :invalid_operation  :division_by_zero  :rounded  :inexact
rounding :: :down  :half_up  :half_even  :ceiling  :floor  :half_down  :up
t :: %Decimal{sign: 1  1, coef: non_neg_integer  :qNaN  :sNaN  :inf, exp: integer}
Functions
Specs:
The absolute value of given number. Sets the number’s sign to positive.
Specs:
Adds two numbers together.
Exceptional conditions
 If one number is Infinity and the other +Infinity
:invalid_operation
will be signalled.
Specs:
Compares two numbers numerically. If the first number is greater than the second
#Decimal<1>
is returned, if less than Decimal<1>
is returned. Otherwise,
if both numbers are equal Decimal<0>
is returned.
Specs:
 decimal?(any) :: boolean
Returns true
if argument is a decimal number; otherwise false
.
Specs:
Divides two numbers.
Exceptional conditions
 If both numbers are (+)Infinity
:invalid_operation
is signalled.  If both numbers are (+)0
:invalid_operation
is signalled.  If second number (denominator) is (+)0
:division_by_zero
is signalled.
Specs:
Divides two numbers and returns the integer part.
Exceptional conditions
 If both numbers are (+)Infinity
:invalid_operation
is signalled.  If both numbers are (+)0
:invalid_operation
is signalled.  If second number (denominator) is (+)0
:division_by_zero
is signalled.
Specs:
Integer division of two numbers and the remainder. Should be used when both
div_int/2
and rem/2
is needed. Equivalent to: `{Decimal.div_int(x, y),
Decimal.rem(x, y)}`.
Exceptional conditions
 If both numbers are (+)Infinity
:invalid_operation
is signalled.  If both numbers are (+)0
:invalid_operation
is signalled.  If second number (denominator) is (+)0
:division_by_zero
is signalled.
Specs:
Compares two numbers numerically and returns true
if they are equal,
otherwise false
.
Specs:
 get_context :: Decimal.Context.t
Gets the process’ context.
Specs:
 inf?(t) :: boolean
Returns true
if number is (+)Infinity; otherwise false
.
Specs:
Compares two values numerically and returns the maximum. Unlike most other
functions in Decimal
if a number is NaN the result will be the other number.
Only if both numbers are NaN will NaN be returned.
Specs:
Compares two values numerically and returns the minimum. Unlike most other
functions in Decimal
if a number is NaN the result will be the other number.
Only if both numbers are NaN will NaN be returned.
Specs:
Negates the given number.
Specs:
Multiplies two numbers.
Exceptional conditions
 If one number is (+0) and the other is (+)Infinity
:invalid_operation
is signalled.
Specs:
 nan?(t) :: boolean
Returns true
if number is NaN; otherwise false
.
Specs:
Creates a new decimal number from a string representation, an integer or a
floating point number. Floating point numbers will be converted to decimal
numbers with :io_lib_format.fwrite_g/1
, since this conversion is not exact
it is recommended to give an integer or a string when possible.
A decimal number will always be created exactly as specified with all digits kept  it will not be rounded with the context.
BNFC
sign ::= ’+’  ’’
digit ::= ’0’  ’1’  ’2’  ’3’  ’4’  ’5’  ’6’  ’7’  ’8’  ’9’
indicator ::= ’e’  ’E’
digits ::= digit [digit]...
decimalpart ::= digits ’.’ [digits]  [’.’] digits
exponentpart ::= indicator [sign] digits
infinity ::= ’Infinity’  ’Inf’
nan ::= ’NaN’ [digits]  ’sNaN’ [digits]
numericvalue ::= decimalpart [exponentpart]  infinity
numericstring ::= [sign] numericvalue  [sign] nan
Specs:
 new(1  1, non_neg_integer  :qNaN  :sNaN  :inf, integer) :: t
Creates a new decimal number from the sign, coefficient and exponent such that
the number will be: sign * coefficient * 10^exponent
.
A decimal number will always be created exactly as specified with all digits kept  it will not be rounded with the context.
Specs:
Applies the context to the given number rounding it to specified precision.
Specs:
Reduces the given number. Removes trailing zeros from coefficient while keeping the number numerically equivalent by increasing the exponent.
Specs:
Remainder of integer division of two numbers. The result will have the sign of the first number.
Exceptional conditions
 If both numbers are (+)Infinity
:invalid_operation
is signalled.  If both numbers are (+)0
:invalid_operation
is signalled.  If second number (denominator) is (+)0
:division_by_zero
is signalled.
Specs:
Rounds the given number to specified decimal places with the given strategy (default is to round to nearest one). If places is negative, at least that many digits to the left of the decimal point will be zero.
Specs:
 set_context(Decimal.Context.t) :: :ok
Set the process’ context.
Specs:
Subtracts second number from the first. Equivalent to Decimal.add/2
when the
second number’s sign is negated.
Exceptional conditions
 If one number is Infinity and the other +Infinity
:invalid_operation
will be signalled.
Specs:
Converts given number to its string representation.
Options
:scientific
 Number converted to scientific notation.:normal
 Number converted without a exponent.:raw
 Number converted to it’s raw, internal format.
Specs:
 update_context((Decimal.Context.t > Decimal.Context.t)) :: :ok
Update the process’ context.
Specs:
 with_context(Decimal.Context.t, (() > x)) :: x when x: var
Runs function with given context.