2017-10-07 120 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 
相關問題