Balanced Ternary in MATLAB
I wanted to do something with balanced ternary the other day, so I wrote this MATLAB class.
classdef bt % Class for managing numbers in balanced ternary. % properties (SetAccess='private') trits = ''; end methods function obj=bt(args) % Constructor. There are two forms. One takes a double % containing an integer value. The other takes a string % containing the characters u, n, and o. % if (isa(args,'char') && size(args,1) == 1) if ~all(args=='u' | args=='o' | args=='n') error('bad trits') end obj.trits = trim_leading(args); elseif (isa(args,'double') && numel(args) == 1) obj.trits = trim_leading(double_to_trits(args)); end end function disp(obj) % Display method % disp(obj.trits) end function r = double(obj) % Convert to double % t = obj.trits; r = 0; while ~isempty(t) r = r*3; if (t(1) == 'u') r = r+1; elseif (t(1) == 'n') r = r-1; end t = t(2:end); end end function r = plus(a,b) % Plus operator. % % addition table for balanced ternary % + n o u % n nu n o % o n o u % u o u un % r_lut = ['u' 'n' 'o' 'n' 'o' 'u' 'o' 'u' 'n']; c_lut = ['n' 'o' 'o' 'o' 'o' 'o' 'o' 'o' 'u']; % Normalize the 2 inputs to the longest+1 by % padding with 'o's. al = size(a.trits,2); bl = size(b.trits,2); len = 1+max(al,bl); a = [repmat('o',1,len-al) a.trits]; b = [repmat('o',1,len-bl) b.trits]; % convert to numbers va = repmat(2,1,len) - (a=='n') + (a=='u'); vb = repmat(2,1,len) - (b=='n') + (b=='u'); % sum and convert into lut indices v = 1+(va-1)+3*(vb-1); % do the lookup r = bt(r_lut(v)); % check for carries c = c_lut(v); if any(c~='o') r = r + bt([c(2:end) 'o']); end end function r = ne(a,b) % Not equal operator % al = size(a.trits,2); bl = size(b.trits,2); len=max(al,bl); atrits = a.trits; btrits = b.trits; if (al ~= len) atrits = [repmat('o',1,len-al) atrits]; end if (bl ~= len) btrits = [repmat('o',1,len-bl) btrits]; end r = atrits ~= btrits; end end end function d = trim_leading(s) start = regexp(s,'[nu][nuo]*','start'); d = s(start:end); end function trits = double_to_trits(src) trits = []; target = src; pos = 0; val = 1; goal = 2*target; if (goal < 0) goal = -goal; end while ((val= 0) if (abs(target-val) < abs(target)) if (val > 0) trits = [trits 'u']; target = target-val; else trits = [trits 'n']; target = target-val; end else trits = [trits 'o']; end val = val/3; pos = pos-1; if ((target*val) < 0) val = -val; end end end
Now I can do things like this:
>> x = bt(512) x = unouoon >> x + x ans = uuunonu >> double(ans) ans = 1024
Pretty neat, huh?