Racing Dog's Kennel Base Minus 2









BM2 Demonstrator

Base Minus 2? Before you conclude that I've really lost it, consider this. We are told that a number base N must be a positive integer N >= 2 aren't we? But any integer N can be raised to any integer power, so, if we can raise 2 to integer powers to give us the bits of a binary number, we could also, if we wanted, raise -2 to those same powers and place the resulting set of ones and zeros next to each other to form a number, yes? We could do the same for any base, but let's stay with -2 by way of providing a simple demonstration.

Hence we should be able to count in base -2. Here is a sample 5 bit count.......

Dec.16-84-21
-1001010
-901011
-801000
-701001
-601110
-501111
-401100
-301101
-200010
-100011
000000
100001
200110
300111
400100
500101
611010
711011
811000
911001
1011110
1111111
1211100
1311101
1410010
1510011
1610000
1710001
1810110
1910111
2010100
2110101

Thus it seems we can count, though the pattern is slightly more complex than normal binary. The value range covered is also more lopsided than usual, being -10 to +21. The other thing to note is that the sign of the number is inherent in the bit pattern, there is no need for a sign bit.

Counting is all well and good, but before we can say we have a viable number base we also need to be able to perform arithmetic operations. If you take a traditional computing view of say addition, you might think in terms of throwing a load of bits at a combinational circuit along with a set of flip-flops. Having banged my head against that particular brick wall back around 1970 when this idea first occured to me, I would advise againts it! Not you understand, that I was the first to think of negative bases! The problem is carries. Consider 1 + 1, we want to get that to produce 2, but a quick check with the table above shows that instead of carrying one bit, we need to be carrying two bits. If on the other hand you want to add 1 + 3 we soon realise that to get 4 simply by carrying pairs of ones after each bit addition produces entirely the wrong answer. There are other problems too! In fact that consideration made me abandon the whole idea until 2020. We all got locked down and got bored and wanted things to do didn't we? So I dragged the idea out and kicked it around a bit!

Eventually I decided to just do it all the long way, one bit at a time and see what problems came up by doing one sample addition at a time. I still wasn't convinced there was a solution, despite making gradual progress in terms of the number of calculations that worked. Then, suddenly, lo! Everything worked! Having said that, you wouldn't want to perform the following algorithm as mental arithmetic......

    function Add ( x, y : word ; bits : integer ) : word ;

        var i              : integer ;
            z, mask        : word ;
            carry1, carry2 : boolean ;

    begin
        mask := 1 ;
        z  := 0 ;
        // two carries as 1 + 1 needs to generate 110
        // i.e. a +4 and a -2
        Carry1 := false ;
        Carry2 := false ;
        for i := 1 to bits do
        begin
            // the shifting of z inserts a 0, so we only need
            // to figure out when to set a 1 instead, plus what
            // to do about carries
            if odd ( x ) and odd ( y ) then  // 1 1
            begin
                if Carry1 or Carry2 then
                begin
                    z  := z or mask ;
                    Carry1 := not Carry2 ;
                    Carry2 := Carry1 ;
                end
                else
                begin
                    Carry1 := true ;
                    Carry2 := true ;
                end
            end
            else if odd ( x ) or odd ( y ) then // 0 1 or 1 0
            begin
                if Carry1 or Carry2 then
                begin
                    if Carry1 then
                    begin
                        Carry1 := not Carry2 ;
                        Carry2 := Carry1 ;
                    end
                    else
                    begin
                        Carry1 := true ;
                        Carry2 := true ;
                    end
                end
                else
                begin
                    z  := z or mask ;
                    Carry1 := Carry2 ;
                    Carry2 := false ;
                end
            end
            else  // 0 0
            begin
                if Carry1 then
                    z  := z or mask ;
                Carry1 := Carry2 ;
                Carry2 := false ;
            end ;
            x := x shr 1 ;
            y := y shr 1 ;
            mask := mask shl 1 ;
        end ;

        // Alternatively, use these flags to cause
        // raising of an overflow exception
        if Carry1 then
            z := z or mask ;
        mask := mask shl 1 ;
        if Carry2 then
            z := z or mask ;

        Add := z  ;
    end ;
		

Of course, to do anything practical we are also going to need Subtraction. Once we have that we can also do multiplication by repeated addition and division by repeated subtraction. But I'll stick to just adding subtraction for now. You should be able to the rest if you really want it!

So, how do we do subtraction? We know how we do it in normal binary, we just translate "A - B" into "A + Twos Complement ( B )". What then is the Base Minus 2 Complement? Well yay! After not seeing it for ages I've finally (2023) figured it and put it into V1.1 of the Demonstrator. Essentially we need two variables, call them O for original, and C for Complement, and a flag Invert (initially false) then what we have to do, scanning bit by bit from the right is...

If Invert is set then, clear Invert, invert the bit into C
Otherwise, if the bit in O is a 1 then copy it to C and set Invert
Either way, step on to the next bit until all have been scanned
		
Simples! Full details of the implementation are in the .pas file included in the distribution. One thing you will notice from that is that we need an extra, undisplayed, bit at the MSB end of the inputs. This is entirely equivalent to having a sign bit in binary integers, but the use is different. It is used to indicate -2048 when doing the complement operation.

Conclusion : It would seem that conventional wisdom needs amending. Instead of

    a number base N is a positve integer where N >= 2
		
    we should have

    a number base N is an integer where |N| >= 2
	
    There again perhaps there should be a qualifier to indicate that to be easily used, N should be positive.
		

Is there anything useful that negative bases could be used for? Not a lot is the short answer, although maybe you could use them to transmit data if you wanted to obfuscate the values without recourse to complex encryption. Oh! Encryption! Maybe that's why we are told that negative bases are not possible because it's a big secret? Oops, just blown that one then. No doubt conspiracy theorists will jump on that as being a serious comment!

Here is the setup file for the demonstrator. I have included the Lazarus source files to prove that Base Minus 2 addition and subtraction can really be performed.

NOTE to programmers : Lazarus/Free Pascal string grids have additional features which I have used, to whit...
  1. Design time setting of initial contents
  2. A Columns property, contains column objects which can have differing formats
  3. Column objects contain Title objects for the same reason
So if you want to use a different language, even Delphi, you are going to have to add code to simulate those effects. It is easier to just download Lazarus!