2015-05-15 47 views
6

Do the nature of floating-point math, .4 * .4 = 0.16000000000000003 ở Julia. Tôi muốn nhận được câu trả lời đúng về mặt toán học của 0.16, theo cách hiệu quả của CPU. Tôi biết round() hoạt động, nhưng điều đó đòi hỏi kiến ​​thức trước về số chữ số thập phân mà câu trả lời chiếm, vì vậy nó không phải là một giải pháp chung.Số học thập phân chính xác trong Julia

+1

Floating điểm toán đã được giải quyết. Thực tế là trường hợp cụ thể này là do các vấn đề đó có thể là câu trả lời mà OP đang tìm kiếm. Câu thứ hai (làm thế nào để có được câu trả lời chính xác trong Julia) một phần có vẻ hợp pháp ... Anh ta không phải là sau khi tất cả gắn liền với việc sử dụng điểm nổi. –

+2

"Cách cpu chuyên sâu nhất" là gì - tại sao bạn thậm chí còn quan tâm đến hiệu suất khi bạn thậm chí không có tính chính xác? –

+6

Một lựa chọn hợp lý trong Julia là số học hợp lý: '4 // 10 * 4 // 10' ->' 4 // 25', và kết quả của 'float (4 // 25)' thực sự là số dấu phẩy động gần nhất đến 0,16. –

Trả lời

9

Một số tùy chọn:

  1. Sử dụng inbuilt Rational loại. Cách chính xác nhất và nhanh nhất sẽ là

    16 // 100 * 16 // 100

Nếu bạn đang sử dụng số rất lớn những có thể tràn, trong trường hợp này bạn có thể sử dụng BigInt s thay vào đó,

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

(bạn không thực sự cần phải bọc tất cả trong big s, vì lý do sẽ tự động quảng bá). Bạn cũng có thể sử dụng rationalize(0.16), nhưng điều này có thể không hoàn toàn chính xác hoặc hiệu quả, vì chữ số 0.16 đã được chuyển đổi thành Float64 vào lúc Julia nhìn thấy nó, vì vậy bạn đang chuyển đổi sang dấu phẩy động nhị phân và sau đó đến một số Rational.

  1. kết thúc triển khai Intel IEEE-754 Dấu phẩy thập phân. Điều này nên được hợp lý nhanh (mặc dù không hiệu quả như nhị phân), nhưng có độ chính xác cố định, vì vậy bạn sẽ phải làm tròn tại một số điểm.

  2. Decimals.jl là thư viện dấu phẩy động "thập phân lớn": vì nó sử dụng số học chính xác tùy ý, nó sẽ chậm hơn DecFP.

Để nói đó là tốt nhất sẽ đòi hỏi thêm thông tin về mục đích sử dụng của bạn.

+0

Lưu ý rằng DecFP.jl cũng * nhanh hơn * so với sử dụng loại BigFloat tích hợp (do sử dụng bất biến) –

0

Bạn có thể sử dụng Python của decimal.Decimal với PyCall, nhưng hiệu quả sẽ là Python ràng buộc

nhập gói:

julia> using PyCall 

julia> @pyimport decimal 

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

Meta-xác định hoạt động (Tôi nghĩ rằng tất cả các loại định nghĩa nên một phần của 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 một số toán học với họ:

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

kết quả Nhận:

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

Xin lỗi, nhưng tôi sẽ không mang tất cả Python chỉ để giải quyết vấn đề này, khi gói DecFP.jl của Steven Johnson hoạt động rất tốt, không thêm nhiều chi phí cho Julia và thậm chí còn nhanh hơn việc sử dụng BigFloat! –

Các vấn đề liên quan