Live data from Hacker News

How to pack ternary numbers in 8-bit bytes

compilade.net

11–20 of 55 posts

Re: How to pack ternary numbers in 8-bit bytes

#13
post #7

> Fixed point numbers to the rescue! > a diagram that shows that dividing 0x7F (127) by 243 and then multiplying by 256 results in 0x86 (134) > Tada! How... how does that help with anything? > Now digits can be easily extracted from the top two bits of the resulting 10-bit number when multiplying this 8-bit byte by 3. What? Why? How? This is supposed to be the most insightful part of the post, and it's literally just…

I think the key insight here is that 243 is 100000 in base3. So dividing by 243 essentially converts any 5 digit base 3 number to [0,1) interval. Multiplying by 256 converts it to [0,256) interval which conveniently fits into a byte.

Re: How to pack ternary numbers in 8-bit bytes

#15
post #5

Earlier quoted context omitted.

Off the top of my head. Compilers. You may know that a value has known 1s and 0s and unknowns. This would allow you to represent that for optimisation purposes.

Arturo[0] language supports true,false and maybe. I really liked that idea actually, worth mentioning here. so valid arturo code can be like (picked from their in-a-nutshell documentation) i1: true i2: false i3: maybe [0]: https://arturo-lang.io/documentation/in-a-nutshell

Everyone hates null but (in database land, and arguably in other programming) it just means “no data.”

(As an aside, I found the characterisation of null as being a “billion dollar mistake” to be unfair. Those who don’t acknowledge null are doomed to reimplement it, probably poorly, or to have the unknowns in their logic remain unknown unknowns.)

Re: How to pack ternary numbers in 8-bit bytes

#16
post #13
post #7

> Fixed point numbers to the rescue! > a diagram that shows that dividing 0x7F (127) by 243 and then multiplying by 256 results in 0x86 (134) > Tada! How... how does that help with anything? > Now digits can be easily extracted from the top two bits of the resulting 10-bit number when multiplying this 8-bit byte by 3. What? Why? How? This is supposed to be the most insightful part of the post, and it's literally just…

I think the key insight here is that 243 is 100000 in base3. So dividing by 243 essentially converts any 5 digit base 3 number to [0,1) interval. Multiplying by 256 converts it to [0,256) interval which conveniently fits into a byte.

It's kinda remarkable this works given how base 2 and base 3 are incredibly poorly aligned and make for a kind of worst case scenario when it comes to division (e.g. 1/3 = 1/2 - 1/4 + 1/8 - 1/16 + 1/32 ... and 1/2 = 1/3 + 1/9 + 1/27 + 1/81 + ...)

Re: How to pack ternary numbers in 8-bit bytes

#17
post #14

How does this packing/unpacking scheme compare to just using a lookup table?

I was wondering the same thing.

Obviously, it partly depends on the implementation machine, how big a hole the tables blow in your cache, how fast the multiplies are, etc.

But it probably also hugely depends on the format that you want your trits in. If you use them unpacked, e.g. one trit per byte, then even if you're using tables, you still have to do a lot of manipulation (e.g. either shifting and oring, or having different tables, and a table lookup per trit and adding together to get the binary).

Re: How to pack ternary numbers in 8-bit bytes

#18

Would having 16 bits to pack a tuple of ternary numbers have a potential to give even better efficiency?

No.

The article suggests using 8 bits (=256 values) to pack 5 trits (=243 values).

If you use 16 bits (=65536 values) then you can pack at most 10 whole trits (=59049 values). 11 trits (=177147 values) won't fit.

The current top comment, by JoshTriplett, analyses what you would need to beat the efficiency.

Re: How to pack ternary numbers in 8-bit bytes

#19
I was actually mucking with ChatGPT about possible "post-binary" architectures.

I ended up feeling that ternary is just icky, because the "middle value" doesn't have an "opposite"

Maybe we should do what quaternions did to complex numbers and just jump from 2 to 4: Quaternary CPUs

I couldn't understand half of the words it spat out but it turns out that using pairs of "quits" as the atomic computation unit to represent complex numbers and/or 2x2 matrices could be ideal for AI etc.

Re: How to pack ternary numbers in 8-bit bytes

#20

It's impressive how close to optimal this is. You can beat the efficiency of 5 trits in 8 bits (1.6) with as few as 17 trits in 27 bits (~1.588), but once you account for rounding up to a whole number of bytes for practical reasons, then beating the efficiency requires going to at least 111 trits in 176 bits (~1.586), or perhaps more practically for fast unpacking, 161 trits in 256 bits (~1.59). At that level, even i…

[deleted]
Post reply on HN