2015-05-15 24 views
6

the nature of floating-point math, .4 * .4 = 0.16000000000000003 Julia'da. 0.16'un matematiksel olarak doğru cevabını CPU-verimli bir şekilde elde etmek istiyorum. Round() çalışmalarını biliyorum, ancak bu sorunun cevabının ondalık basamak sayısı hakkında önceden bilgisi olmasını gerektirir, bu yüzden genel bir çözüm değildir.Julia'da tam onlu aritmetik

+1

Kayan nokta matematik ele alınmıştır. Bu özel durumun bu sorunlardan kaynaklanmış olması, OP'nin aradığı cevap olabilir. İkincisi (Julia'da doğru cevabı nasıl alacağınız) kısmı meşru görünüyor ... Kayan nokta kullanmak için her şeyden sonra değil. –

+2

"En düşük cpu yoğun yolu nedir" - niçin daha doğrusu olmadığın zaman, performansa neden önem veriyorsun? –

+6

Julia'da makul bir seçenek rasyonel aritmetik: '4 // 10 * 4 // 10' ->' 4 // 25', ve 'float (4 // 25)' sonucu gerçekten en yakın kayan nokta sayısıdır 0.16'ya. –

cevap

9

bazı seçenekler:

  1. dahili Rational türünü kullanın. En doğru ve en hızlı şekilde,

    16 // 100 * 16 // 100

bunun yerine BigInt kullanabilirsiniz s bu durumda bu taşabilir çok büyük sayılar kullanıyorsanız,

olurdu

big(16)//big(100) * big(16)//big(100) 

(rationals otomatik teşvik edecektir olarak aslında, big s hepsini sarmak için gerekmez).

Ayrıca rationalize(0.16) kullanabilirsiniz, ancak bu edebi 0.16 zaten Julia gördüğü zaman bir Float64 dönüştürüldükten gibi bir ikili kayan nokta dönüştürme ediyoruz, böylece, oldukça olduğunca doğru veya verimli olmayabilir ve daha sonra Rational'a.

  1. IEEE-754 ondalık kayan nokta Intel uygulanmasını sarar . Bu, mantıklı bir şekilde hızlı olmalı (ikili kadar verimli olmasa da), ancak sabit bir hassasiyete sahip olmalıdır, bu yüzden bir noktada yuvarlanmanız gerekecektir.

  2. Decimals.jl bir "büyük ondalık" kayan nokta kitaplığıdır: isteğe bağlı kesinlik aritmetiğini kullandığından, DecFP'den daha yavaş olacaktır.

Hangisi en iyisi, kullanım amacınız hakkında daha fazla bilgi gerektirdiğini söylemek.

+0

Not: DecFP.jl ayrıca yerleşik BigFloat türünü kullanmadan * daha hızlı * olduğunu unutmayın (immutables kullanarak) –

0

Sen Python en decimal.DecimalPyCall ile ancak verimlilik Python

bağlı olacak kullanabilirsiniz İthalat paketi:

julia> using PyCall 

julia> @pyimport decimal 

julia> const Dec = decimal.Decimal 
PyObject <class 'decimal.Decimal'> 

Ben tanımların bu tür tüm olması gerektiğini düşünüyorum (operasyonlarını Meta tanımlamak PyCall parçası):!

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 

onlarla bazı matematik yapın:

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') 

al sonucu:

julia> y[:to_eng_string]() |> float 
0.4 
+1

Üzgünüz, ama Steven Johnson DecFP.jl paketi, bunu çözmek için tüm Python'u getirmezdim. Çok iyi çalışıyor, Julia'ya fazla yük getirmiyor ve BigFloat'ı kullanmaktan daha hızlı! –