4

好吧,从表面上看,我有一个简单的问题。我想将无理数的小数部分取到指定的位数并将其视为整数。例如,如果我的无理数是 2.657829...并且我想要五位数,我正在寻找 65782(尽管我实际上正在处理“大”数字)。

这很容易使用字符串来实现,例如,如果我想要根 3 到 50 位的小数部分:

function main_1(n::Int, m::Int)::BigInt
    setprecision(Int(trunc((m + 3) * log2(10))))
    sr = string(sqrt(big(n)))
    ff = findfirst(sr, '.')
    dp = parse(BigInt, sr[ff + 1:ff + m])
    return dp
end

@time main_1(3, 50)

输出是73205080756887729352744634150587236694280525381038

但是,当我只处理数字时,我讨厌使用字符串!我想要做的是从 BigFloat 开始,减去整数部分,将结果乘以适当的 10 因子,将结果四舍五入为零,然后将其转换为 BigInt。问题是 Julia 使用科学/指数表示法,所以我似乎无法仅使用数字来实现我想要的。以下(部分)代码显示了问题:

function main_2(n::Int, m::Int)::BigFloat
    setprecision(Int(trunc((m + 3) * log2(10))))
    sr = sqrt(big(n))
    tr = trunc(sr)
    dp = (sr - tr) * big(10.0) ^ 50
    return dp
end

@time main_2(3, 50)

这种情况下的输出是7.32050807568877293527446341505872366942805253810380625e+49(在舍入阶段会删除一些额外的数字)。

所以我的问题是,有没有什么方法可以在不诉诸字符串的情况下实现我的目标?

4

1 回答 1

3

One way to achive this, without using strings, is to convert the result and it's integer part to BigInt before do the subtract (and change the function type from BigFloat to BigInt):

function main_2(n::Int, m::Int)::BigInt
    setprecision(Int(trunc((m + 3) * log2(10))))

    # Calc the sqrt
    result = sqrt(big(n))

    # Convert the whole number to BigInt to the specified precision
    sr = convert(BigInt, trunc(result*big(10)^m))

    # Convert the integer part to BigInt
    tr = convert(BigInt, trunc(result)*big(10)^m)

    dp = sr - tr
    return dp
end

Comparing the above implementation with the main_1 function, there is a little improvement:

julia> @time main_1(3, 50)
  0.000042 seconds (36 allocations: 5.254 KiB)
73205080756887729352744634150587236694280525381038

julia> @time main_2(3, 50)
  0.000028 seconds (51 allocations: 1.617 KiB)
73205080756887729352744634150587236694280525381038

Edit:

Other way (as commented by @Bill) is just trunc the result (to get rid of InexactError()) and change the function type to BigInt:

function main_2(n::Int, m::Int)::BigInt
    setprecision(Int(trunc((m + 3) * log2(10))))
    sr = sqrt(big(n))
    tr = trunc(sr)
    dp = (sr - tr) * big(10.0) ^ 50
    return trunc(dp)
end

After testing:

julia> @time main_2(3,50)
  0.000026 seconds (28 allocations: 1.016 KiB)
73205080756887729352744634150587236694280525381038
于 2018-06-21T03:08:08.770 回答