Wegen the nature of floating-point math, .4 * .4
= 0.16000000000000003
in Julia. Ich möchte die mathematisch korrekte Antwort von 0.16
CPU-effizient erhalten. Ich weiß round() funktioniert, aber das erfordert vorherige Kenntnis der Anzahl der Dezimalstellen, die die Antwort belegt, also ist es keine allgemeine Lösung.Genaue Dezimalarithmetik in Julia
Antwort
Einige Optionen:
den eingebauten
Rational
Typ verwenden. Die genaueste und schnellste Weg16 // 100 * 16 // 100
wäre, wenn Sie sehr große Zahlen mit diesen überlaufen könnte, in welchem Fall Sie BigInt
s stattdessen verwenden können,
big(16)//big(100) * big(16)//big(100)
(Sie brauchen nicht wirklich, sie alle in big
s zu wickeln, da die rationals automatisch fördern).
Sie können auch rationalize(0.16)
verwenden, aber dies ist vielleicht nicht ganz so genau oder effizient sein, wie die wörtlichen 0.16
bereits ein Float64
durch die Zeit, Julia es sieht umgewandelt worden, so dass Sie in eine binären Gleitkomma konvertieren und dann zu einem Rational
.
wickelt die Intel Implementierung von IEEE-754 Gleitpunktberechnungen. Dies sollte ziemlich schnell sein (obwohl nicht so effizient wie Binär), aber hat eine feste Präzision, so dass Sie irgendwann runden müssen.
Decimals.jl ist eine „große dezimal“ Punkt Bibliothek floating: wie es mit beliebiger Genauigkeit arithmetische verwendet, ist es langsamer als DecFP sein wird.
zu sagen, was das Beste ist, mehr Informationen über Ihre beabsichtigte Verwendung erforderlich.
Beachten Sie, dass DecFP.jl ist auch * schneller * als die Verwendung der integrierten BigFloat-Typ (aufgrund der Verwendung von immutables) –
können Sie Python verwenden decimal.Decimal
mit PyCall
, aber Effizienz Python
Import das Paket gebunden sein wird:
julia> using PyCall
julia> @pyimport decimal
julia> const Dec = decimal.Decimal
PyObject <class 'decimal.Decimal'>
Meta-Definition-Operationen (Ich denke, alle diese Art von Definitionen sein sollte Teil 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
mit ihnen etwas Mathematik tun:
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 Ergebnis:
julia> y[:to_eng_string]() |> float
0.4
Sorry, aber ich würde nicht alle von Python nur um dies zu lösen, wenn Steven Johnson DecFP.jl Paket funktioniert sehr gut, fügt Julia nicht viel Overhead hinzu und ist sogar schneller als BigFloat! –
Gleitkomma-Mathematik wurde behoben. Die Tatsache, dass dieser spezielle Fall durch diese Probleme verursacht wurde, könnte die Antwort sein, nach der OP gesucht hat. Die zweite (wie man die richtige Antwort in Julia bekommt) scheint legitim zu sein ... Er ist nicht auf die Verwendung von Fließkomma angewiesen. –
"Was ist der am wenigsten CPU-intensive Weg" - warum kümmert es Sie überhaupt um die Performance, wenn Sie noch nicht einmal die Korrektheit hatten? –
Eine vernünftige Option in Julia ist rationale Arithmetik: '4 // 10 * 4 // 10' ->' 4 // 25', und das Ergebnis von 'float (4 // 25)' ist tatsächlich die nächste Fließkommazahl zu 0,16. –