Get a number from an array of digits

后端 未结 2 726
悲哀的现实
悲哀的现实 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
    
    0 讨论(0)
  • 2021-01-25 08:06

    The answer seems to be written directly within the documentation of digits:

    
    help?> digits
    search: digits digits! ndigits isdigit isxdigit disable_sigint
    
      digits([T<:Integer], n::Integer; base::T = 10, pad::Integer = 1)
    
      Return an array with element type T (default Int) of the digits of n in the given base,
      optionally padded with zeros to a specified size. More significant digits are at higher
      indices, such that n == sum([digits[k]*base^(k-1) for k=1:length(digits)]).
    

    So for your case this will work:

    julia> d = digits(36, base = 4);
    
    julia> sum([d[k]*4^(k-1) for k=1:length(d)])
    36
    

    And the above code can be shortened with the dot operator:

    julia> sum(d.*4 .^(0:(length(d)-1)))
    36
    
    0 讨论(0)
提交回复
热议问题