由于Julia中的the nature of floating-point math,.4 * .4
= 0.16000000000000003
。我希望以CPU高效的方式获得0.16
的数学正确答案。我知道round()有效,但这需要事先知道答案所占的小数位数,所以这不是一般的解决方案。
答案 0 :(得分:10)
一些选项:
使用内置的Rational
类型。最准确,最快捷的方式是
16 // 100 * 16 // 100
如果您使用非常大的数字,这些可能会溢出,在这种情况下,您可以改为使用BigInt
,
big(16)//big(100) * big(16)//big(100)
(你实际上并不需要将它们全部包装在big
中,因为理性会自动提升)。
您也可以使用rationalize(0.16)
,但这可能不那么准确或有效,因为在Julia看到它之前,文字0.16
已经转换为Float64
,因此,您要转换为二进制浮点数,然后转换为Rational
。
DecFP.jl包含了IEEE-754十进制浮点的英特尔实现。这应该相当快(虽然效率不如二进制),但具有固定的精度,因此您必须在某个时刻进行舍入。
Decimals.jl是"大小数"浮点库:因为它使用任意精度算术,它将比DecFP慢。
要说哪个最好,需要有关您的预期用途的更多信息。
答案 1 :(得分:1)
您可以将Python decimal.Decimal
与PyCall
一起使用,但效率将受到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