The Decimals
package provides basic data type and functions for arbitrary precision decimal floating point arithmetic in Julia. It supports addition, subtraction, negation, multiplication, division, and equality operations.
Why is this needed? The following code in Julia gives an answer
julia> 0.1 + 0.2
0.30000000000000004
In words, the binary floating point arithmetics implemented in computers has finite resolution - not all real numbers (even within the limits) can be expressed exactly. While many scientific and engineering fields can handle this behavior, it is not acceptable in fields like finance, where it's important to be able to trust that $0.30 is actually 30 cents, rather than 30.000000000000004 cents.
julia> Pkg.add("Decimals")
or just Ctrl
+]
and
(v1.2) pkg> add Decimals
julia> using Decimals
Decimal
is constructed by passing values s
, c
, q
such that
x = (-1)^s * c * 10^q
:
julia> Decimal(0, 1, -1)
0.1
julia> Decimal(1, 1, -1)
-0.1
You can parse Decimal
objects from strings:
julia> x = "0.2"
"0.2"
julia> parse(Decimal, x)
0.2
julia> tryparse(Decimal, x)
0.2
Parsing support scientific notation. Alternatively, you can use the @dec_str
macro, which also supports the thousands separator _
:
julia> dec"0.2"
0.2
julia> dec"1_000.000_001"
1000.000001
Any real number can be converted to a Decimal
:
julia> Decimal(0.2)
0.2
julia> Decimal(-10)
-10
A Decimal
can be converted to numeric types that can represent it:
julia> Float64(Decimal(0.2))
0.2
julia> Int(Decimal(10))
10
julia> Float64(Decimal(0, 1, 512))
ERROR: ArgumentError: cannot parse "100[...]" as Float64
julia> Int(Decimal(0.4))
ERROR: ArgumentError: invalid base 10 digit '.' in "0.4"
A string in the decimal form of a Decimal
can be obtained via
string(::Decimal)
:
julia> string(Decimal(0.2))
"0.2"
The 2- and 3-args methods for show
are implemented:
julia> repr(Decimal(1000000.0))
"Decimal(0, 10, 5)"
julia> repr("text/plain", Decimal(1000000.0))
"1.0E+6"
julia> x, y = decimal("0.2"), decimal("0.1");
julia> string(x + y)
"0.3"
julia> string(x - y)
"0.1"
julia> string(-x)
"-0.2"
julia> string(x * y)
"0.02"
julia> string(x / y)
"2"
julia> string(inv(x))
"5"
julia> [x y] .* 2
2-element Array{Decimal,1}:
Decimal(0,1,-1)
Decimal(0,5,-2)
julia> x == decimal("0.2")
true
julia> x != decimal("0.1")
true
julia> x >= y
true
julia> isless(x, y)
false
julia> x == 0.2
true
julia> round(decimal(3.1415), digits=2)
Decimal(0,314,-2)
julia> string(ans)
"3.14"
Unlike another Julia package called DecFP
, which aims at implementing the IEEE 754-2008 standard introducing 32, 64, and 64-bit precisions (decimal32, decimal64 and decimal128, respectively), this package allows arbitrary precision. Note, however, that in comparision with DecFP
, which is is essentially a wrapper for a specialized Intel® Decimal Floating-Point Math Library, the present package is more computationally demanding. If more computational efficiency is demanded, functions from libmpdec
library can be called directly.
The closest equivalent (and inspiration) for the present package in Python is the standard built-in decimal
package, which is based on General Decimal Arithmetic Specification by IBM. Since version 3.3 of Python, it is actually libmpdec
/cdecimal
that is under the hood.
There is a standard test suite called
DecTests. The test suite is
provided in a custom format. We
have a script scripts/dectest.jl
for translating test cases from the custom
format to common Julia tests. The script should be called like this:
julia scripts/dectest.jl <testset name> <dectest path> <output path>
For example:
julia scripts/dectest.jl Plus dectests/plus.decTest test/dectests/test_plus.jl
.
We put these test files into the test/dectests
subdirectory.
- What Every Programmer Should Know About Floating-Point Arithmetic!?! or Why don’t my numbers add up? floating-point-gui.de.
- Decimal Floating Point https://en.wikipedia.org/wiki/Decimal_floating_point
- IEEE 754-2008 revision https://en.wikipedia.org/wiki/IEEE_754-2008_revision
- 754-2008 - IEEE Standard for Floating-Point Arithmetic https://ieeexplore.ieee.org/document/4610935 Superseeded by 754-2019 - IEEE Standard for Floating-Point Arithmetic https://ieeexplore.ieee.org/document/8766229
- Intel® Decimal Floating-Point Math Library https://software.intel.com/en-us/blogs/2008/03/06/intel-decimal-floating-point-math-library/
- General Decimal Arithmetic Specification, IBM, Version 1.70 – 7 Apr 2009 http://speleotrove.com/decimal/decarith.html
mpdecimal
,libmpdec
- C/C++ library http://www.bytereef.org/mpdecimal/index.htmldecimal
- Decimal fixed point and floating point arithmetic, module for Python https://docs.python.org/2/library/decimal.html