2015-05-15 15 views
6

the nature of floating-point math, .4 * .4 = 0.16000000000000003 जूलिया में। मैं एक CPU-कुशल तरीके से 0.16 का गणितीय सही उत्तर प्राप्त करना चाहता हूं। मुझे राउंड() काम पता है, लेकिन इसके लिए जवाब देने वाले दशमलव स्थानों की संख्या के पूर्व ज्ञान की आवश्यकता है, इसलिए यह एक सामान्य समाधान नहीं है।जूलिया में सटीक दशमलव अंकगणित

+1

चल बिन्दु गणित संबोधित किया गया है। तथ्य यह है कि यह विशिष्ट मामला उन मुद्दों के कारण हुआ था, वह उत्तर हो सकता है जिसे ओपी ढूंढ रहा था। दूसरा (जूलिया में सही उत्तर कैसे प्राप्त करें) भाग वैध लगता है ... वह फ्लोटिंग पॉइंट का उपयोग करने के लिए बंधे नहीं है। –

+2

"कम से कम सीपीयू गहन तरीका क्या है" - आप तब तक प्रदर्शन की परवाह क्यों करते हैं जब आपके पास अभी तक शुद्धता भी न हो? –

+6

जूलिया में एक उचित विकल्प तर्कसंगत अंकगणितीय है: '4 // 10 * 4 // 10' ->' 4 // 25', और 'फ्लोट (4 // 25) 'का परिणाम वास्तव में निकटतम फ़्लोटिंग पॉइंट नंबर है 0.16 तक। –

उत्तर

9

कुछ विकल्प:

  1. इनबिल्ट Rational प्रकार का उपयोग करें। सबसे सटीक और तेज़ तरीका

    16 // 100 * 16 // 100

तुम बहुत बड़ी संख्या इन अतिप्रवाह हो सकता है, इस स्थिति में आप BigInt रों बजाय का उपयोग कर सकते उपयोग कर रहे हैं हो सकता है,

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

(आप वास्तव में के रूप में परिमेय स्वचालित रूप से बढ़ावा देंगे, उन सब को big रों में रैप करने के लिए की जरूरत नहीं है)।

तुम भी rationalize(0.16) उपयोग कर सकते हैं, लेकिन यह काफी के रूप में सही या कुशल नहीं हो सकता है के रूप में शाब्दिक 0.16 पहले से ही समय जूलिया इसे देखता है के द्वारा एक Float64 में बदल दिया गया है, तो आप एक द्विआधारी चल बिंदु में रूपांतरित करते हैं और फिर Rational पर।

  1. IEEE-754 दशमलव चल बिन्दु के इंटेल कार्यान्वयन गिर्द घूमती है। यह उचित रूप से तेज़ होना चाहिए (हालांकि बाइनरी के रूप में उतना कुशल नहीं है), लेकिन सटीकता तय कर दी है, इसलिए आपको किसी बिंदु पर गोल करना होगा।

  2. Decimals.jl एक "बड़ा दशमलव" फ़्लोटिंग पॉइंट लाइब्रेरी है: क्योंकि यह मनमाने ढंग से सटीक अंकगणित का उपयोग करता है, यह डीसीएफपी से धीमा होने वाला है।

यह कहने के लिए कि सबसे अच्छा क्या है, आपके इच्छित उपयोग के बारे में अधिक जानकारी की आवश्यकता होगी।

+0

ध्यान दें कि बिल्टफ्लैट प्रकार (अपरिवर्तनीय उपयोग करने के कारण) का उपयोग करने से DecFP.jl भी * तेज * है। –

0

आप उपयोग कर सकते हैं पायथन के decimal.DecimalPyCall साथ, लेकिन क्षमता अजगर बाध्य

होने जा रहा है आयात पैकेज:

julia> using PyCall 

julia> @pyimport decimal 

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

मेटा-परिभाषित परिचालन (मुझे लगता है कि परिभाषाओं इस तरह के सभी होना चाहिए 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 

उनके साथ कुछ गणित कार्य करें:

0,123,
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') 

प्राप्त परिणाम:

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

क्षमा करें, लेकिन मैं इसे हल करने के लिए सभी पायथन नहीं लाऊंगा, जब स्टीवन जॉनसन का DecFP.jl पैकेज बहुत अच्छी तरह से काम करता है, जूलिया के लिए ज्यादा ओवरहेड नहीं जोड़ता है, और BigFloat का उपयोग करने से भी तेज़ है! –