Юлия: Преобразование векторов в числа с основанием n - PullRequest
3 голосов
/ 25 сентября 2019

Мне нужна функция, которая интерпретирует векторы целых чисел как числа с определенной базой, как это:

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

Следующая функция выполняет свою работу, но мне немного неловко:

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

Есть ли лучший способ сделать это в стиле Джулии, возможно, даже встроенная функция или модуль для этого?

Заранее спасибо!

Ответы [ 2 ]

5 голосов
/ 25 сентября 2019

Вы можете написать:

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

, который, вероятно, самый короткий и быстрый.Измените его на foldl((x,y) -> b*x+y, v, init=0) в вызове, если вы хотите, чтобы это работало и для пустого вектора, возвращающего 0.

Есть некоторые альтернативы, которые также пришли мне в голову, поэтому я публикую их ниже.

Первый сравнительно короткий (не быстрый) способ сделать это:

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

Что-то в вашей реализации будет:

f(v, b) = sum(x -> b^(x[1]-1)*x[2], enumerate(Iterators.reverse(v)))
2 голосов
/ 25 сентября 2019

То, что вы написали, определенно хорошо в стиле Джулии.Вы просто выбрали слегка неэффективный алгоритм.Лучше избегать возведения в степень, поскольку это дорогостоящая операция, которая выполняет здесь много лишней работы (вычисление b^n за одну итерацию, а затем b^(n+1) на следующей явно неэффективно.)

Вот реализацияэто в основном то же самое, что и первое решение @ BogumilKaminski, просто записанное в виде цикла (циклы в стиле Юлии), и, очевидно, также немного быстрее, чем использование foldl:

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