Negative base

A negative base (or negative radix) may be used to construct a non-standard positional numeral system. Like other place-value systems, each position holds multiples of the appropriate power of the system's base; but that base is negative—that is to say, the base \scriptstyle b is equal to \scriptstyle -r for some natural number \scriptstyle r (r ≥ 2).

Negative-base systems can accommodate all the same numbers as standard place-value systems, but both positive and negative numbers are represented without the use of a minus sign (or, in computer representation, a sign bit); this advantage is countered by an increased complexity of arithmetic operations. The need to store the information normally contained by a negative sign often results in a negative-base number being one digit longer than its positive-base equivalent.

The common names for negative-base positional numeral systems are formed by prefixing nega- to the name of the corresponding positive-base system; for example, negadecimal (base −10) corresponds to decimal (base 10), negabinary (base −2) to binary (base 2), and negaternary (base −3) to ternary (base 3).[1][2]

Example

Consider what is meant by the representation 12,243 in the negadecimal system, whose base \scriptstyle b is −10:

multiples of \scriptstyle b^4
(i.e., 10,000)
multiples of \scriptstyle b^3
(i.e., −1,000)
multiples of \scriptstyle b^2
(i.e., 100)
multiples of \scriptstyle b^1
(i.e., −10)
multiples of \scriptstyle b^0
(i.e., 1)
1 2 2 4 3

Since 10,000 + (−2,000) + 200 + (−40) + 3 = 8,163, the representation 12,243 in negadecimal notation is equivalent to 8,163 in decimal notation. While -8,163 in decimal would be written 9,977 in negadecimal.

History

Negative numerical bases were first considered by Vittorio Grünwald in his work Giornale di Matematiche di Battaglini, published in 1885.[3] Grünwald gave algorithms for performing addition, subtraction, multiplication, division, root extraction, divisibility tests, and radix conversion. Negative bases were later independently rediscovered by A. J. Kempner in 1936[4] and Zdzisław Pawlak and A. Wakulicz in 1959.[5]

Negabinary was implemented in the early Polish computer BINEG (and UMC), built 1957–59, based on ideas by Z. Pawlak and A. Lazarkiewicz from the Mathematical Institute in Warsaw.[6] Implementations since then have been rare.

Notation and use

Denoting the base as -r, every integer a can be written uniquely as

a = \sum_{i=0}^{n}d_{i}(-r)^{i}

where each digit \scriptstyle d_k is an integer from 0 to \scriptstyle r - 1 and the leading digit \scriptstyle d_n is \scriptstyle > 0 (unless \scriptstyle n=0). The base \scriptstyle -r expansion of \scriptstyle a is then given by the string \scriptstyle d_n d_{n-1} \ldots d_1 d_0.

Negative-base systems may thus be compared to signed-digit representations, such as balanced ternary, where the radix is positive but the digits are taken from a partially negative range.

Some numbers have the same representation in base \scriptstyle -r as in base r. For example, the numbers from 100 to 109 have the same representations in decimal and negadecimal. Similarly,

17=2^4+2^0=(-2)^4+(-2)^0

and is represented by 10001 in binary and 10001 in negabinary.

Some numbers with their expansions in a number of positive and corresponding negative bases are:

Decimal Negadecimal Binary Negabinary Ternary Negaternary
−15 25 −1111 110001 −120 1220
 :  :  :  :  :  :
−5 15 −101 1111 −12 21
−4 16 −100 1100 −11 22
−3 17 −11 1101 −10 10
−2 18 −10 10 −2 11
−1 19 −1 11 −1 12
0 0 0 0 0 0
1 1 1 1 1 1
2 2 10 110 2 2
3 3 11 111 10 120
4 4 100 100 11 121
5 5 101 101 12 122
6 6 110 11010 20 110
7 7 111 11011 21 111
8 8 1000 11000 22 112
9 9 1001 11001 100 100
10 190 1010 11110 101 101
11 191 1011 11111 102 102
12 192 1100 11100 110 220
13 193 1101 11101 111 221
14 194 1110 10010 112 222
15 195 1111 10011 120 210
16 196 10000 10000 121 211
17 197 10001 10001 122 212

Note that the base \scriptstyle -r expansions of negative integers have an even number of digits, while the base \scriptstyle -r expansions of the non-negative integers have an odd number of digits.

Calculation

The base \scriptstyle -r expansion of a number can be found by repeated division by \scriptstyle  -r, recording the non-negative remainders of \scriptstyle  0, 1,\ldots r-1, and concatenating those remainders, starting with the last. Note that if \scriptstyle  a / b = c, remainder d, then \scriptstyle  bc + d = a. For example, in negaternary:

\begin{align}
 146 & ~/~ -3 = & -48, & ~\mbox{remainder}~ 2 \\
 -48 & ~/~ -3 = &  16, & ~\mbox{remainder}~ 0 \\
  16 & ~/~ -3 = &  -5, & ~\mbox{remainder}~ 1 \\
  -5 & ~/~ -3 = &   2, & ~\mbox{remainder}~ 1 \\
   2 & ~/~ -3 = &   0, & ~\mbox{remainder}~ 2 \\
\end{align}

Reading the remainders backward we obtain the negaternary expression of 146: 21102.

Note that in most programming languages, the result (in integer arithmetic) of dividing a negative number by a negative number is rounded towards 0, usually leaving a negative remainder. In such a case we have \scriptstyle  a = (-r)c + d = (-r)c + d - r + r = (-r)(c + 1) + (d + r). Because \scriptstyle |d| < r, \scriptstyle (d + r) is the positive remainder. Therefore, to get the correct result in such case, computer implementations of the above algorithm should add 1 and r to the quotient and remainder respectively (shown below in the Python programming language):

def negaternary(i):
    digits = []
    if not i:
        digits = ['0']
    else:
        while i != 0:
            i, remainder = divmod(i, -3)
            if remainder < 0:
                i, remainder = i + 1, remainder + 3
            digits.append(str(remainder))
    return ''.join(digits[::-1])

C# implementation:

static string negaternary(int value)
{
	string result = string.Empty;

	while (value != 0)
	{
		int remainder = value % -3;
		value = value / -3;

		if (remainder < 0)
		{
			remainder += 3;
			value += 1;
		}

		result = remainder.ToString() + result;
	}

	return result;
}

Common Lisp implementation:

(defun negaternary (i)
  (if (zerop i)
      "0"
      (let ((digits "")
	    (rem 0))
	(loop while (not (zerop i)) do
	     (progn
	       (multiple-value-setq (i rem) (truncate i -3))
	       (when (minusp rem)
	         (incf i)
	         (incf rem 3))
	       (setf digits (concatenate 'string (write-to-string rem) digits))))
	digits)))

Visual Basic implementation:

 1 Private Shared Function ToNegaternary(value As Integer) As String
 2 	Dim result As String = String.Empty
 3 
 4 	While value <> 0
 5 		Dim remainder As Integer = value Mod -3
 6 		value /= -3
 7 
 8 		If remainder < 0 Then
 9 			remainder += 3
10 			value += 1
11 		End If
12 
13 		result = remainder.ToString() & result
14 	End While
15 
16 	Return result
17 End Function

To Negative Base

PHP implementation. The conversion from integer to some negative base:

function toNegativeBase($no, $base)
{
	$digits = array();
	$base = intval($base);
	while ($no != 0) {
		$temp_no = $no;
		$no = intval($temp_no / $base);
		$remainder = ($temp_no % $base);
 
		if ($remainder < 0) {
			$remainder += abs($base);
			$no++;
		}
 
		array_unshift($digits, $remainder);
	}
 
	return $digits;
}

Visual Basic implementation:

Function toNegativeBase(Number As Integer , base As Integer) As System.Collections.Generic.List(Of Integer)

	Dim digits As New System.Collections.Generic.List(Of Integer)
	while Number <> 0
		Dim remainder As Integer= Number Mod base
		Number = CInt(Number / base)
 
		if remainder < 0 then
			remainder += system.math.abs(base)
			Number+=1
		end if
 
		digits.Insert(0, remainder)
	end while
 
	return digits
end function

To Negabinary

The conversion to negabinary (base -2; digits \scriptstyle \in \; \{0,1\}) allows a remarkable shortcut (C implementation):

unsigned int toNegaBinary(unsigned int value) // input in standard binary
{
	unsigned int Schroeppel2 = 0xAAAAAAAA; // = 2/3*((2*2)^16-1) = ...1010
	return (value + Schroeppel2) ^ Schroeppel2; // eXclusive OR
	// resulting unsigned int to be interpreted as string of elements ε {0,1} (bits)
}

Due to D. Librik (Szudzik). The bitwise XOR portion is originally due to Schroeppel (1972).[7]

JavaScript port for the same shortcut calculation:

function toNegaBinary( number ) {
    var Schroeppel2 = 0xAAAAAAAA;
    // Convert to NegaBinary String
    return ( ( number + Schroeppel2 ) ^ Schroeppel2 ).toString(2);
}

To Negaquaternary

The conversion to negaquaternary (base -4; digits \scriptstyle \in \; \{0,1,2,3\}) allows a similar shortcut (C implementation):

unsigned int toNegaQuaternary(unsigned int value) // input in standard binary
{
	unsigned int Schroeppel4 = 0xCCCCCCCC; // = 4/5*((2*4)^8-1) = ...11001100 = ...3030
	return (value + Schroeppel4) ^ Schroeppel4; // eXclusive OR
	// resulting unsigned int to be interpreted as string of elements ε {0,1,2,3} (pairs of bits)
}

JavaScript port for the same shortcut calculation:

function toNegaQuaternary( number ) {
    var Schroeppel4 = 0xCCCCCCCC;
    // Convert to NegaQuaternary String
    return ( ( number + Schroeppel4 ) ^ Schroeppel4 ).toString(4);
}

Arithmetic operations

The following describes the arithmetic operations for negabinary; calculations in larger bases are similar.

Addition

To add two negabinary numbers, start with a carry of 0, and, starting from the least significant bits, add the bits of the two numbers plus the carry. The resulting number is then looked up in the following table to get the bit to write down as result, and the next carry:

Number Bit Carry Comment
−2 0 1 −2 occurs only during subtraction.
−1 1 1
0 0 0
1 1 0
2 0 −1
3 1 −1 3 occurs only during addition.

The second row of this table, for instance, expresses the fact that −1 = 1 + 1 × −2; the fifth row says 2 = 0 + −1 × −2; etc.

As an example, to add 1010101 (1 + 4 + 16 + 64 = 85) and 1110100 (4 + 16 − 32 + 64 = 52),

carry:          1 −1  0 −1  1 −1  0  0  0
first number:         1  0  1  0  1  0  1
second number:        1  1  1  0  1  0  0 +
               --------------------------
number:         1 −1  2  0  3 −1  2  0  1
bit (result):   1  1  0  0  1  1  0  0  1
carry:          0  1 −1  0 −1  1 −1  0  0

so the result is 110011001 (1 − 8 + 16 − 128 + 256 = 137).

Another Method

While adding two negabinary numbers, every time a carry is generated an extra carry should be propagated to next bit. Consider same example as above

extra carry:       1  1  0  1  0  0  0     
carry:          1  0  1  1  0  1  0  0  0
first number:         1  0  1  0  1  0  1
second number:        1  1  1  0  1  0  0 +
               --------------------------
Answer:         1  1  0  0  1  1  0  0  1

Subtraction

To subtract, multiply each bit of the second number by −1, and add the numbers, using the same table as above.

As an example, to compute 1101001 (1 − 8 − 32 + 64 = 25) minus 1110100 (4 + 16 − 32 + 64 = 52),

carry:          0  1 −1  1  0  0  0
first number:   1  1  0  1  0  0  1
second number: −1 −1 −1  0 −1  0  0 +
               --------------------
number:         0  1 −2  2 −1  0  1
bit (result):   0  1  0  0  1  0  1
carry:          0  0  1 −1  1  0  0

so the result is 100101 (1 + 4 −32 = −27).

To negate a number, compute 0 minus the number.

Multiplication and division

Shifting to the left multiplies by −2, shifting to the right divides by −2.

To multiply, multiply like normal decimal or binary numbers, but using the negabinary rules for adding the carry, when adding the numbers.

first number:                   1  1  1  0  1  1  0
second number:                  1  0  1  1  0  1  1 *
              -------------------------------------
                                1  1  1  0  1  1  0
                             1  1  1  0  1  1  0

                       1  1  1  0  1  1  0
                    1  1  1  0  1  1  0

              1  1  1  0  1  1  0                   +
              -------------------------------------
carry:        0 −1  0 −1 −1 −1 −1 −1  0 −1  0  0
number:       1  0  2  1  2  2  2  3  2  0  2  1  0
bit (result): 1  0  0  1  0  0  0  1  0  0  0  1  0
carry:           0 −1  0 −1 −1 −1 −1 −1  0 −1  0  0

For each column, add carry to number, and divide the sum by −2, to get the new carry, and the resulting bit as the remainder.

Fractional numbers

Base \scriptstyle -r representation may of course be carried beyond the radix point, allowing the representation of non-integral numbers.

As with positive-base systems, terminating representations correspond to fractions where the denominator is a power of the base; repeating representations correspond to other rationals, and for the same reason.

Non-unique representations

Unlike positive-base systems, where integers and terminating fractions have non-unique representations (for example, in decimal 0.999… = 1) in negative-base systems the integers have only a single representation. However, there do exist rationals with non-unique representations; for example, in negaternary,

0.(02)\ldots_{(-3)} = \frac{1}{4} = 1.(20)\ldots_{(-3)}.

Such non-unique representations can be found by considering the largest and smallest possible representations with integral parts 0 and 1 respectively, and then noting that they are equal. (Indeed, this works with any integral-base system.) The rationals thus non-uniquely expressible are those of form

\frac{ar + 1}{b(r + 1)}.

Imaginary base

Main article: Complex-base system

Just as using a negative base allows the representation of negative numbers without an explicit negative sign, using an imaginary base allows the representation of Gaussian integers. Donald Knuth proposed the quater-imaginary base (base 2i) in 1955.[8]

Imaginary-base arithmetic is not much different from negative-base arithmetic, since an imaginary-base number may be considered as the interleave of its real and imaginary parts; using INTERCAL-72 notation,

x(2i) + (2i)y(2i) = x(2i) ¢ y(2i).

See also

References

  1. Knuth, Donald (1998), The Art of Computer Programming, Volume 2 (3rd ed.), pp. 204–205. Knuth mentions both negabinary and negadecimal.
  2. The negaternary system is discussed briefly in Petkovšek, Marko (1990), "Ambiguous numbers are dense", The American Mathematical Monthly 97 (5): 408–411, doi:10.2307/2324393, ISSN 0002-9890, MR 1048915.
  3. Vittorio Grünwald. Giornale di Matematiche di Battaglini (1885), 203-221, 367
  4. Kempner, A. J. (1936), "Anormal Systems of Numeration", American Mathematical Monthly 43 (10): 610–617, doi:10.2307/2300532, MR 1523792.
  5. Pawlak, Z.; Wakulicz, A. (1957), "Use of expansions with a negative basis in the arithmometer of a digital computer", Bulletin de l'Academie Polonaise des Scienses, Classe III 5: 233–236.
  6. Marczynski, R. W., "The First Seven Years of Polish Computing", IEEE Annals of the History of Computing, Vol. 2, No 1, January 1980
  7. See the MathWorld Negabinary link
  8. D. Knuth. The Art of Computer Programming. Volume 2, 3rd Edition. Addison-Wesley. pp. 205, "Positional Number Systems"

Further reading

External links

This article is issued from Wikipedia - version of the Saturday, January 16, 2016. The text is available under the Creative Commons Attribution/Share Alike but additional terms may apply for the media files.