## DEV Community is a community of 848,284 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Anthony

Posted on

# Deterministic Base Conversion with Logarithms

## Intro

This article walks through several solutions for a decimal to octal number convertor coding challenge written in ruby.
Note: These solutions can be generalized for converting decimal to any base less than 10 by adding a second function parameter and replacing all 8's with the given parameter.

## Solution 1: Standard Way

One simple way to convert bases is to repeatedly take the modulo of the input number and target base `num % 8` then divide the input number by target base`num /= 8` until the number is empty `while num > 0`. Each modulo result is either added to an array or summed into a resultant number like in the example below.

``````def octal_convertor(num)
octal = 0
i = 1
while num > 0
octal += (num % 8) * i
num /= 8
i *= 10
end
return octal
end
``````

This solution uses a variable `i = 1` which grows by `i *= 10` on each iteration. It is used to multiply `num % 8` so it goes in the next whole number place in `octal += (num % 8) * i`. You can think of it like slicing off base 8 digits from `num` and slotting them into the next whole number place in `octal`

## Solution 2: Deterministic Iteration with Logarithm

The number of places(digits) in a whole number of any base(base 8 in this instance) can be calculated with `Math.log(num,8).floor + 1`. This reveals how many digits need to be 'sliced' out with `num % 8`, or rather the number of loop iterations required. So there is no need to check if `num > 0`, we can just run a loop an exact number of times.

``````def octal_convertor(num)
octal = 0
(Math.log(num,8).floor + 1).times do |i|
octal += (num % 8) * 10**i
num /= 8
end
return octal
end
``````

The `.times` method accepts a block and passes iteration count to `|i|`. So in addition to knowing the exact number of iterations in advance the 'i' variable in the previous solutions is provided by `.times`. The `|i|` increments from zero, so to slot the octal digits in the right place `(num % 8)` is multiplied by `10**i`.

## Solution 3: Number as an Array

This one-liner works much the same way as above but creates a new array with a length of the octal number (so there is a place for each oct digit). Similar to `.times` `Array.new` accepts a block where you can fill each value in the array with something, this block receives an index value `|i|`.

``````def octal_convertor(num)
Array.new(Math.log(num,8).floor + 1) {|i| ((num / 8**i) % 8) * 10**i }.sum
end
``````

`num` is not mutably divided with `num /= 8`, instead, using 'i' we calculate how many times it should have been divided `num / 8**i` or rather which octal place value the current iteration is at. `10**i` works exactly the same as previously mentioned. The array now contains all oct digits multiplied by `10**i`, which provides the correct number of zeros added so when summed together they fit in the right place. `.sum` adds all numbers in the array together returning the converted number.

## Conclusion

Calculating number digit lengths using logarithms provides a means to determine iteration count ahead of time and iterate over enumerable objects(arrays, numbers) instead of using while loops.