Due to the nature of floating-point math, .4 * .4
= 0.16000000000000003
in Julia. I want to get the mathematically correct answer of 0.16
, in a CPU-efficient way. I know round() works, but that requires prior knowledge of the number of decimal places the answer occupies, so it isn't a general solution.

- 3,395
- 19
- 31

- 491
- 4
- 12
-
1Floating point math has been addressed. The fact that this specific case was caused by those issues might be the answer that OP was looking for. The second (how to get correct answer in Julia) part seems legitimate... He is not after all tied to using floating point. – Barry Gackle May 15 '15 at 16:55
-
2"What is the least cpu intensive way" – why do you even care about performance when you didn't even have correctness yet? – The Paramagnetic Croissant May 15 '15 at 16:55
-
6A reasonable option in Julia is rational arithmetic: `4//10 * 4//10` -> `4//25`, and the result of `float(4//25)` is indeed the closest floating point number to 0.16. – mbauman May 15 '15 at 16:58
-
2Try https://github.com/stevengj/DecFP.jl – ptb May 15 '15 at 17:56
-
1@BarryGackle I agree, and I've edited to salvage the question. Consider editing it yourself next time. – Jeffrey Bosboom May 16 '15 at 01:09
2 Answers
Some options:
Use the inbuilt
Rational
type. The most accurate and fastest way would be16//100 * 16//100
If you're using very big numbers these might overflow, in which case you can use BigInt
s instead,
big(16)//big(100) * big(16)//big(100)
(you don't actually need to wrap them all in big
s, as the rationals will promote automatically).
You can also use rationalize(0.16)
, but this may not be quite as accurate or efficient, as the literal 0.16
has already been converted to a Float64
by the time Julia sees it, so you're converting to a binary floating point and then to a Rational
.
DecFP.jl wraps the Intel implementation of IEEE-754 Decimal floating point. This should be reasonably fast (though not as efficient as binary), but has fixed precision, so you will have to round at some point.
Decimals.jl is a "big decimal" floating point library: as it uses arbitrary precision arithmetic, it is going to be slower than DecFP.
To say which is the best would require more information about your intended use.

- 3
- 2

- 7,694
- 1
- 26
- 50
-
2Note that DecFP.jl is also *faster* than using the built-in BigFloat type (due to using immutables) – Scott Jones Apr 30 '16 at 12:17
You can use Python's decimal.Decimal
with PyCall
, but efficiency is going to be Python bound
Import the package:
julia> using PyCall
julia> @pyimport decimal
julia> const Dec = decimal.Decimal
PyObject <class 'decimal.Decimal'>
Meta-define operations (I think all of these kind of definitions should be part of PyCall
!):
julia> py_methods = Dict(
:+ => :__add__,
:* => :__mul__,
:- => :__sub__,
(:/) => :__truediv__
)
Dict{Symbol,Symbol} with 4 entries:
:/ => :__truediv__
:+ => :__add__
:* => :__mul__
:- => :__sub__
julia> for (op, meth) in py_methods
op = Expr(:quote, op)
meth = Expr(:quote, meth)
@eval Base.($op){T<:PyObject}(x::T, y::T) = x[$meth](y)
end
Do some math with them:
julia> x = Dec("0.4")
PyObject Decimal('0.4')
julia> x * x
PyObject Decimal('0.16')
julia> x + x
PyObject Decimal('0.8')
julia> x - x
PyObject Decimal('0.0')
julia> x / x
PyObject Decimal('1')
julia> y = x + x * x / x - x
PyObject Decimal('0.4')
Get result:
julia> y[:to_eng_string]() |> float
0.4

- 7,633
- 37
- 52
-
3Sorry, but I wouldn't bring all of Python in just to solve this, when Steven Johnson's DecFP.jl package works very well, doesn't add much overhead to Julia, and is even faster than using BigFloat! – Scott Jones Apr 30 '16 at 12:16