2015-05-15 13 views
6

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

+1

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. –

+2

"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? –

+6

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. –

Antwort

9

Einige Optionen:

  1. den eingebauten Rational Typ verwenden. Die genaueste und schnellste Weg

    16 // 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.

  1. 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.

  2. 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.

+0

Beachten Sie, dass DecFP.jl ist auch * schneller * als die Verwendung der integrierten BigFloat-Typ (aufgrund der Verwendung von immutables) –

0

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 
+1

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! –