universal_amateur
universal_amateur

Reputation: 149

Julia: Convert Vectors to Numbers with Base n

I need a function which interprets vectors of integers as numbers with a certain base like this:

vectonum([1,2,3,4], 10) #=> 1234
vectonum([0,0,0,1], 2) #=> 1
vectonum([1,1,1,1], 2) #=> 15

The following function does the job, but looks a little bit awkward to me:

function vectonum(vector, base)
  result = 0
  vector = reverse(vector)
  for (idx, val) in enumerate(vector)
    val_ = val * base ^ (idx - 1)
    result += val * base ^ (idx - 1)
  end
  return result
end

Is there a better, more julia-style way to do this, perhaps even a built-in function or module for this?

Thanks in advance!

Upvotes: 3

Views: 808

Answers (2)

DNF
DNF

Reputation: 12644

What you wrote is definitely good Julia-style. You just chose a slightly inefficient algorithm. It's better to avoid exponentiation, since that is an expensive operation that does a lot of redundant work here (calculating b^n in one iteration and then b^(n+1) in the next is clearly inefficient.)

Here's an implementation that is basically the same as @BogumilKaminski's first solution, just written out as a loop (loops are Julia-style), and apparently also slightly faster than using foldl:

function vectonum(d, base=10)
   s = zero(eltype(d))
   for val in d
      s = s * base + val
   end
   return s
end

Upvotes: 2

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69819

You can write:

f(v, b) = foldl((x,y) -> b*x+y, v)

which is probably shortest and fast. Change it to foldl((x,y) -> b*x+y, v, init=0) in the call if you want this to work also for empty vector returning 0.

There are some alternatives that also came to my mind, so I post them below.

First the relatively short (not fast) way to do it is:

f(v, b) = parse(Int, join(v), base=b)

Something along your implementation would be:

f(v, b) = sum(x -> b^(x[1]-1)*x[2], enumerate(Iterators.reverse(v)))

Upvotes: 6

Related Questions