Get a number from an array of digits

后端 未结 2 725
悲哀的现实
悲哀的现实 2021-01-25 07:16

To split a number into digits in a given base, Julia has the digits() function:

julia> digits(36, base = 4)
3-element Array{Int64,1}:
 0
 1
 2
2条回答
  •  南方客
    南方客 (楼主)
    2021-01-25 08:00

    The previous answers are correct, but there is also the matter of efficiency:

    sum([x[k]*base^(k-1) for k=1:length(x)])
    

    collects the numbers into an array before summing, which causes unnecessary allocations. Skip the brackets to get better performance:

    sum(x[k]*base^(k-1) for k in 1:length(x))
    

    This also allocates an array before summing: sum(d.*4 .^(0:(length(d)-1)))

    If you really want good performance, though, write a loop and avoid repeated exponentiation:

    function undigit(d; base=10)
        s = zero(eltype(d))
        mult = one(eltype(d))
        for val in d
            s += val * mult
            mult *= base
        end
        return s
    end
    

    This has one extra unnecessary multiplication, you could try to figure out some way of skipping that. But the performance is 10-15x better than the other approaches in my tests, and has zero allocations.

    Edit: There's actually a slight risk to the type handling above. If the input vector and base have different integer types, you can get a type instability. This code should behave better:

    function undigits(d; base=10)
        (s, b) = promote(zero(eltype(d)), base)
        mult = one(s)
        for val in d
            s += val * mult
            mult *= b
        end
        return s
    end
    

提交回复
热议问题