Julia中的精确十进制算术

时间:2015-05-15 16:48:02

标签: floating-point julia multiplication

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

2 个答案:

答案 0 :(得分:10)

一些选项:

  1. 使用内置的Rational类型。最准确,最快捷的方式是

    16 // 100 * 16 // 100

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

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

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

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

    1. DecFP.jl包含了IEEE-754十进制浮点的英特尔实现。这应该相当快(虽然效率不如二进制),但具有固定的精度,因此您必须在某个时刻进行舍入。

    2. Decimals.jl是"大小数"浮点库:因为它使用任意精度算术,它将比DecFP慢。

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

答案 1 :(得分:1)

您可以将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