Julia 中的精确十进制算术

Exact decimal arithmetic in Julia

由于 the nature of floating-point math.4 * .4 = 0.16000000000000003 在 Julia 中。我想以 CPU 高效的方式获得 0.16 的数学正确答案。我知道 round() 有效,但这需要事先知道答案占用的小数位数,因此它不是通用解决方案。

部分选项:

  1. 使用内置的 Rational 类型。最准确和最快的方法是

    16//100 * 16//100

如果您使用的数字非常大,这些数字可能会溢出,在这种情况下,您可以改用 BigInts,

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

(您实际上不需要将它们全部包装在 big 中,因为有理数会自动提升)。

您也可以使用 rationalize(0.16),但这可能不那么准确或高效,因为当 Julia 看到时文字 0.16 已经转换为 Float64它,所以你要转换为二进制浮点数,然后转换为 Rational.

  1. DecFP.jl wraps the Intel implementation of IEEE-754 十进制浮点数。这应该相当快(虽然不如二进制有效),但具有固定精度,因此您将不得不在某些时候舍入。

  2. Decimals.jl 是一个 "big decimal" 浮点库:因为它使用任意精度算法,它会比 DecFP 慢。

要说哪个最好,需要更多关于您的预期用途的信息。

您可以将 Python 的 decimal.DecimalPyCall 一起使用,但效率将受到 Python 的限制

导入包:

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

和他们一起做一些数学运算:

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