我有兴趣以字节的形式获取BigFloat的数字。我得到一个非常奇怪的错误,我无法调试。我提供了出现错误的最小示例。
function floatToBytes(x::BigFloat)
ret = zeros(UInt8, 4)
xs = significand(x)/2
b = UInt8(0)
for i = 1:4
xs *= 256
b = trunc(UInt8, xs)
ret[i] = b
xs -= b
end
return ret
end
println( floatToBytes(BigFloat(0.9921875001164153)) )
println( floatToBytes(BigFloat(0.9960937501164153)) )
运行时我得到的是
UInt8[0xfe, 0x00, 0x00, 0x00]
ERROR: LoadError: InexactError()
Stacktrace:
[1] trunc(::Type{UInt8}, ::BigFloat) at ./mpfr.jl:201
等
似乎它不想将255变成UInt8
。我可以通过将函数定义为
function floatToBytes(x::BigFloat)
ret = zeros(UInt8, 4)
xs = significand(x)/2
b = UInt8(0)
for i = 1:4
xs *= 256
try
b = trunc(UInt8, xs)
catch
b = trunc(UInt8, xs-1)+UInt8(1)
end
ret[i] = b
xs -= b
end
return ret
end
但这非常令人不满意。这是怎么回事?
答案 0 :(得分:3)
对于BigFloat,问题看起来像trunc
中的错误。问题是当前代码(typemin(T) <= x <= typemax(T)) || throw(InexactError(:trunc, T, x))
会抛出错误,因为x
大于255,即typemax。
它实际上需要在BigFloat域中执行trunc
然后强制转换为T(并对typemax进行强制转换检查)。
我已经在https://github.com/JuliaLang/julia/issues/24041
打开了一个相关问题与此同时,解决方案可能是:
UInt8(trunc(xs))
即。先trunc
然后再施放。例如:
julia> UInt8(trunc(BigFloat(0.9960937501164153)*256))
0xff