The base expansion of a number can be found by repeated division by , recording the non-negative remainders in \{0, 1, \ldots, r-1\}, and concatenating those remainders, starting with the last. Note that if is with remainder , then and therefore . To arrive at the correct conversion, the value for must be chosen such that is non-negative and minimal. For the fourth line of the following example this means that : -5 \div (-3) = 2 ~\mathrm{remainder}~ 1 has to be chosen — and not = 3 ~\mathrm{remainder}~ 4 nor = 1 ~\mathrm{remainder}~ -\!2. For example, to convert 146 in decimal to negaternary: : \begin{array}{rr} 146 \div (-3) = & -48 ~\mathrm{remainder}~ 2 \\ -48 \div (-3) = & 16 ~\mathrm{remainder}~ 0 \\ 16 \div (-3) = & -5 ~\mathrm{remainder}~ 1 \\ -5 \div (-3) = & 2 ~\mathrm{remainder}~ 1 \\ 2 \div (-3) = & 0 ~\mathrm{remainder}~ 2 \end{array} Reading the remainders backward we obtain the negaternary representation of 14610: 21102–3. : Proof: −3 · (−3 · (−3 · (−3 · (
2 ) +
1 ) +
1 ) +
0 ) +
2 = (((
2 · (−3) +
1) · (−3) +
1) · (−3) +
0) · (−3) +
2 = 14610. Reading the remainders
forward we can obtain the negaternary least-significant-digit-first representation. : Proof:
2 + (
0 + (
1 + (
1 + (
2 ) · −3 ) · −3) · −3 ) · −3 = 14610. 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 . Because , is the positive remainder. Therefore, to get the correct result in such case, computer implementations of the above algorithm should add 1 and to the quotient and remainder respectively.
Example implementation code To negabinary C# static string ToNegabinary(int val) { string result = string.Empty; while (val != 0) { int remainder = val % -2; val = val / -2; if (remainder
C++ auto to_negabinary(int value) { std::bitset result; std::size_t bit_position = 0; while (value != 0) { const auto div_result = std::div(value, -2); if (div_result.rem
To negaternary C# static string Negaternary(int val) { string result = string.Empty; while (val != 0) { int remainder = val % -3; val = val / -3; if (remainder
Python def negaternary(i: int) -> str: """Decimal to negaternary""" if i == 0: digits = ["0"] else: digits = [] while i != 0: i, remainder = divmod(i, -3) if remainder >>> negaternary(1000) '2212001'
Common Lisp (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)))
To any negative base Java import java.util.ArrayList; import java.util.Collections; public ArrayList negativeBase(int input, int base) { ArrayList result_rev = new ArrayList<>(); int number = input; while (number != 0) { int i = number % base; number /= base; if (i The above gives the result in an ArrayList of integers, so that the code does not have to handle how to represent a base smaller than −10. To display the result as a string, one can decide on a mapping of base to characrters. For example: import java.util.stream.Collectors; final String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_"; public String toBaseString(ArrayList lst) { // Would throw exception if base is beyond the 64 possible characters return lst.stream().map(n -> alphabet[n]).collect(Collectors.joining("")); }
AutoLisp (defun negabase (num baz / dig rst) ;; NUM is any number. ;; BAZ is any number in the interval [-10, -2]. (This is forced by how we do string notation.) ;; ;; NUM and BAZ will be truncated to an integer if they're floats (e.g. 14.25 ;; will be truncated to 14, -123456789.87 to -123456789, etc.). (if (and (numberp num) (numberp baz) ( (fix baz) -11)) (progn (setq baz (float (fix baz)) num (float (fix num)) dig (if (= num 0) "0" "")) (while (/= num 0) (setq rst (- num (* baz (setq num (fix (/ num baz)))))) (if (minusp rst) (setq num (1+ num) rst (- rst baz))) (setq dig (strcat (itoa (fix rst)) dig))) dig) (progn (prompt (cond ((and (not (numberp num)) (not (numberp baz))) "\nWrong number and negabase.") ((not (numberp num)) "\nWrong number.") ((not (numberp baz)) "\nWrong negabase.") (t "\nNegabase must be inside [-10 -2] interval."))) (princ))))
Shortcut calculation The following algorithms assume that • the input is available in
bitstrings and coded in (base +2; digits in \{0, 1\}) (as in most of today's digital computers), • there are add () and xor () operations, which operate on such bitstrings (as in most of today's digital computers), • the set D of output digits is standard, i. e. D = \{0, |b|-1\} with base b\in \{-2,-4\}, • the output is coded in the same bitstring format, but the meaning of the places is another one.
To negabinary The conversion to
negabinary (base −2; digits in \{0, 1\}) allows a remarkable shortcut (C implementation): uint32_t toNegaBinary(uint32_t value) // input in standard binary { uint32_t 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) } JavaScript port for the same shortcut calculation: function toNegaBinary(value) { const Schroeppel2 = 0xAAAAAAAA; // Convert as in C, then convert to a NegaBinary String return ( ( value + Schroeppel2 ) ^ Schroeppel2 ).toString(2); } The algorithm is first described by
Schroeppel in the
HAKMEM (1972) as item 128. The
Wolfram MathWorld documents a version in the Wolfram Language by D. Librik (Szudzik).
To negaquaternary The conversion to
negaquaternary (base −4; digits in \{0, 1, 2, 3\}) allows a similar shortcut (C implementation): uint32_t toNegaQuaternary(uint32_t value) // input in standard binary { uint32_t 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(value) { const Schroeppel4 = 0xCCCCCCCC; // Convert as in C, then convert to NegaQuaternary String return ( ( value + Schroeppel4 ) ^ Schroeppel4 ).toString(4); } == Arithmetic operations ==