gpt4 book ai didi

arrays - Julia:BigFloat 到字节数组

转载 作者:行者123 更新时间:2023-12-04 06:29:12 26 4
gpt4 key购买 nike

我想获取 BigFloat 的二进制数字数字。我认为最简单的方法是将数字转换为字节数组。在 this question有一种方法可以为 Float64 做到这一点,但是当我为 BigFloat 尝试相同的方法时它告诉我 write 没有 BigFloat 的方法.

我怎么能用 Julia 做到这一点?

附注。我知道存在一种将二进制数字作为字符串获取的方法,但是这会带来巨大的开销,我想避免它。

最佳答案

序列化或表示 BigFloats 很棘手,因为:一种。 BigFloat 结构使用指针,而 指向的缓冲区由 GMP 库控制,该库是包装在 Julia 中的外部库。

因此,作为第一步,这里有一些函数可以以准确且易于操作的方式对 BigFloat 进行文本格式化:

# numbits(a) returns the number of significant digits in a BigFloat
# including digits both left and right of floating point.
# For example:
# julia> numbits(BigFloat(3/8)
# 2
#
# This is the trickiest function since it looks slightly into
# the internal representation in GMP of BigInt data.

function numbits(a::BigFloat)
n = a.prec
for i=1:(a.prec>>count_ones(sizeof(Base.GMP.Limb)*8-1))
tz = trailing_zeros(unsafe_load(a.d,i))
n -= tz
if tz < sizeof(Base.GMP.Limb)*8
break
end
end
return n
end
# mantissarep(a) returns a tuple with two elements. The first element is a BigInt
# holding all the significant bits of a BigFloat, and the second holds
# the exponent needed to return the floating point to its position.
# Thus, as an example, the following holds:
# julia> a = BigFloat(1.1)
# 1.100000000000000088817841...
#
# julia> mantissarep(a)
# (2476979795053773, 51)
#
# julia> big"2476979795053773"/big"2"^51 == a
# true
#

mantissarep(a::BigFloat) = (BigInt(a*BigFloat(2)^(numbits(a)-a.exp)),
numbits(a)-a.exp)
# bigfloattext(a) returns an easy textual representation of a BigFloat

function bigfloattext(bf::BigFloat)
(a,b) = mantissarep(bf)
return "$(sign(a)==-1 ? "-" : "")big\"$(dec(abs(a)))\"/big\"2\"^$(b)"
end
# bigfloatbintext(a) returns an easy binary textual representation a BigFloat

function bigfloatbintext(bf::BigFloat)
(a,b) = mantissarep(bf)
return "$(sign(a)==-1 ? "-" : "")big\"0b$(bin(abs(a)))\"/big\"2\"^0b$(bin(b))"
end

使用这些函数,序列化 BigFloat 的一种方法是简单地编写 bigfloattext 的字符串输出。 .这种方法不是很紧凑,但是会很容易反序列化(可以使用 BigFloats 的 parse 方法)并且相对清晰。为了进行更紧凑的序列化, mantissarep 的字节数可以与 BigFloat 的精度字段一起写入。这会使这个答案更长一点,所以如果需要,我会添加。

例如,写:
julia> a = sin(BigFloat(π)/3)    # calculate some BigFloat
8.660254037844386467637231707529361834714026269051903140279034897259665084543988e-01

julia> println(bigfloattext(a)) # represent it as a string
big"100278890836790510567389408543623384672710501789331344711007167057270294106993"/big"2"^256

julia> # show representation is faithful
julia> big"100278890836790510567389408543623384672710501789331344711007167057270294106993"/big"2"^256 == a
true

请注意(关于其他答案)写 d属于 Ptr{Limb} 类型的 BigFloat 的字段(=数据字段)相当无用,可能会导致内存损坏。

更新 :在下面海报评论的指导下,这里有另外几个将 BigFloat 转换为字节表示的函数:
function BigFloat2Bytes(bf::BigFloat)
bf2 = bf/big"2"^exponent(bf)-1.0
bvec = Vector{UInt8}()
push!(bvec,0x01)
while bf2 != 0.0
bf2 *= 256
b = trunc(Int, bf2)
push!(bvec, UInt8(b))
bf2 -= b
end
return (bvec, exponent(bf))
end

function Bytes2BigFloat(bvec, e)
bf = zero(BigInt)
for b in bvec
bf = bf*256 + b
end
return BigFloat(bf*BigFloat(2)^(e-8*length(bvec)+8))
end

有了这些,我们有:
julia> a = BigFloat(123.2323)
1.23232299999999995065991242881...e+02

julia> BigFloat2Bytes(a)
(UInt8[0x01, 0xec, 0xed, 0xe0, 0x0d, 0x1b, 0x71, 0x70], 6)

julia> Bytes2BigFloat(BigFloat2Bytes(a)...)
1.23232299999999995065991242881...e+02

julia> Bytes2BigFloat(BigFloat2Bytes(a)...) == a
true

关于arrays - Julia:BigFloat 到字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46604972/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com