2017-10-07 89 views
1

我有兴趣以字节的形式获取BigFloat的数字。我收到一个非常奇怪的错误,我无法调试。我提供了一个出现错误的最小示例。Julia:尝试获取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 

但是这是非常不令人满意的。这里发生了什么?

+1

它看起来像是BigFloat的'trunc'中的一个bug。它做'(typemin(T)<= x <= typemax(T))||抛出(InexactError(:trunc,T,x))'抛出一个错误,因为'x'大于255,这是typemax。它实际上需要在BigFloat中执行'trunc',然后转换为T(并且对typemax进行转换检查)。你想提出一个问题(或者我应该)吗?代码在'base/mpfr.jl:209' –

+1

啊,你能做到吗? – tst

+1

当然,你可以在函数中使用'UInt8(trunc(BigFloat(0.9960937501164153)* 256))'或'UInt8(trunc(xs))'。我也可以写这个答案。 –

回答

3

这个问题看起来像是BigFloat的trunc中的一个bug。问题是当前代码(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