Fibonacci Encoding (2024-10-29)
I recently learned this cool encoding in my info theory class and wanted to share.
As a forewarning, I am a student still learning and write this as a way of processing the information as I learn it. None of this is peer-reviewed. My writing here may (and likely will) have mistakes.
Lets dive in though! First let us consider representations for a number . There is a greedy algorithm to produce a representation for any number given placeholders. Lets assume we have the placeholders
To represent we
- Find the largest such that
- Find the largest such that
- Put in position
- and repeat (i.e subtract by and go back to step 1)
For example given and typical binary placeholders for , which are
We then step through the algorithm getting the highest placeholder , which we can multiply by at most . This gives us a in position 6. then becomes . We then get , with , and becomes . We then do this again with and to give us:
1 | 1 | 1 | 1 | 0 | 0 |
For the base representations we always have that for some -ary base since the greedy algorithm would pick the larger placeholder. This is because for a -ary base, .
Now let us consider placeholders to be fibonacci. That is we start at , then (to make sure we have that subsequent are strictly greater then previous ones), , , and so on following that
That same number would be represented as
1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
In fibonacci representation. This representation has two important properties
(1) Fibonacci representations only contains 0s and 1s. Why?
Thus, for all placeholders, since multiplying by two is always greater than the next placeholder, the greedy algorithm would have us pick that placeholder rather than multiply by 2.
(2) Fibonacci representations will never have consecutive s. This is because the greedy algorithm will choose the biggest possible placeholder. Thus we would always have instead of .
The second property is how we will leverage this to construct fibonacci encodings, allowing us to encode a stream of integers of unknown length. We do this by
- Creating the fibonacci representation
- Reversing the order (i.e. least significant bit to most)
- Adding a trailing 1.
Going back to our example, the representation of would then be reversed to and then a trailing is added to get us the encoding of .
We essentially encode in the base of the ratio between numbers, in this case we are encoding in the golden ratio . Thus to encode we need roughly bits.
This is roughly times more bits than in binary. However this encoding allows us to send an arbitrary amount of at a time, with a way of punctuating between numbers (something called a universal code).
The robustness of fibonacci comes from the fact that by flipping a bit in the stream, we mess up at most 2 numbers. Contrary to other encoding schemes like Lempel-Ziv, Elias Gamma, Elias Delta, and Elias Omega, flipping one bit has some robustness, and is able to preserve the majority of the stream of integers.
Lastly, although not planned, is the ability to convert units rather easily in this representation. Specifically from kilometers to miles and centimeters to inches. The ratio of kilometers to miles is roughly , in other words there are kilometers in a mile; Therefore, we can shift a bit to the left to convert from miles to kilometers.
() miles becomes () kilometers.
The ratio between centimeters to inches is roughly , and since is roughly , we can a bit shift twice to convert between the two.
() inches becomes () centimeters.
This is purely a coincidence due to the fact that the ratios between these units are close to (or close to a power of) the golden ratio .