I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Imaginary base numbers

Imaginary base numbers
You are encouraged to solve this task according to the task description, using any language you may know.

Imaginary base numbers are a non-standard positional numeral system which uses an imaginary number as its radix. The most common is quater-imaginary with radix 2i.

The quater-imaginary numeral system was first proposed by Donald Knuth in 1955 as a submission for a high school science talent search. [Ref.]

Other imaginary bases are possible too but are not as widely discussed and aren't specifically named.

Task: Write a set of procedures (functions, subroutines, however they are referred to in your language) to convert base 10 numbers to an imaginary base and back.

At a minimum, support quater-imaginary (base 2i).

For extra kudos, support positive or negative bases 2i through 6i (or higher).

As a stretch goal, support converting non-integer numbers ( E.G. 227.65625+10.859375i ) to an imaginary base.

See Wikipedia: Quater-imaginary_base for more details.

For reference, here are some some decimal and complex numbers converted to quater-imaginary.

C

Translation of: C++
`#include <math.h>#include <stdio.h>#include <string.h> int find(char *s, char c) {    for (char *i = s; *i != 0; i++) {        if (*i == c) {            return i - s;        }    }    return -1;} void reverse(char *b, char *e) {    for (e--; b < e; b++, e--) {        char t = *b;        *b = *e;        *e = t;    }} ////////////////////////////////////////////////////// struct Complex {    double rel, img;}; void printComplex(struct Complex c) {    printf("(%3.0f + %3.0fi)", c.rel, c.img);} struct Complex makeComplex(double rel, double img) {    struct Complex c = { rel, img };    return c;} struct Complex addComplex(struct Complex a, struct Complex b) {    struct Complex c = { a.rel + b.rel, a.img + b.img };    return c;} struct Complex mulComplex(struct Complex a, struct Complex b) {    struct Complex c = { a.rel * b.rel - a.img * b.img, a.rel * b.img - a.img * b.rel };    return c;} struct Complex mulComplexD(struct Complex a, double b) {    struct Complex c = { a.rel * b, a.img * b };    return c;} struct Complex negComplex(struct Complex a) {    return mulComplexD(a, -1.0);} struct Complex divComplex(struct Complex a, struct Complex b) {    double re = a.rel * b.rel + a.img * b.img;    double im = a.img * b.rel - a.rel * b.img;    double d = b.rel * b.rel + b.img * b.img;    struct Complex c = { re / d, im / d };    return c;} struct Complex inv(struct Complex c) {    double d = c.rel * c.rel + c.img * c.img;    struct Complex i = { c.rel / d, -c.img / d };    return i;} const struct Complex TWO_I = { 0.0, 2.0 };const struct Complex INV_TWO_I = { 0.0, -0.5 }; ////////////////////////////////////////////////////// struct QuaterImaginary {    char *b2i;    int valid;}; struct QuaterImaginary makeQuaterImaginary(char *s) {    struct QuaterImaginary qi = { s, 0 }; // assume invalid until tested    size_t i, valid = 1, cnt = 0;     if (*s != 0) {        for (i = 0; s[i] != 0; i++) {            if (s[i] < '0' || '3' < s[i]) {                if (s[i] == '.') {                    cnt++;                } else {                    valid = 0;                    break;                }            }        }        if (valid && cnt > 1) {            valid = 0;        }    }     qi.valid = valid;    return qi;} void printQuaterImaginary(struct QuaterImaginary qi) {    if (qi.valid) {        printf("%8s", qi.b2i);    } else {        printf(" ERROR  ");    }} ////////////////////////////////////////////////////// struct Complex qi2c(struct QuaterImaginary qi) {    size_t len = strlen(qi.b2i);    int pointPos = find(qi.b2i, '.');    size_t posLen = (pointPos > 0) ? pointPos : len;    struct Complex sum = makeComplex(0.0, 0.0);    struct Complex prod = makeComplex(1.0, 0.0);    size_t j;     for (j = 0; j < posLen; j++) {        double k = qi.b2i[posLen - 1 - j] - '0';        if (k > 0.0) {            sum = addComplex(sum, mulComplexD(prod, k));        }        prod = mulComplex(prod, TWO_I);    }    if (pointPos != -1) {        prod = INV_TWO_I;        for (j = posLen + 1; j < len; j++) {            double k = qi.b2i[j] - '0';            if (k > 0.0) {                sum = addComplex(sum, mulComplexD(prod, k));            }            prod = mulComplex(prod, INV_TWO_I);        }    }    return sum;} // only works properly if the real and imaginary parts are integralstruct QuaterImaginary c2qi(struct Complex c, char *out) {    char *p = out;    int re, im, fi;     *p = 0;    if (c.rel == 0.0 && c.img == 0.0) {        return makeQuaterImaginary("0");    }     re = (int)c.rel;    im = (int)c.img;    fi = -1;    while (re != 0) {        int rem = re % -4;        re /= -4;        if (rem < 0) {            rem += 4;            re++;        }        *p++ = rem + '0';        *p++ = '0';        *p = 0;    }    if (im != 0) {        size_t index = 1;        struct Complex fc = divComplex((struct Complex) { 0.0, c.img }, (struct Complex) { 0.0, 2.0 });        double f = fc.rel;        im = (int)ceil(f);        f = -4.0 * (f - im);        while (im != 0) {            int rem = im % -4;            im /= -4;            if (rem < 0) {                rem += 4;                im++;            }            if (index < (p - out)) {                out[index] = rem + '0';            } else {                *p++ = '0';                *p++ = rem + '0';                *p = 0;            }            index += 2;        }        fi = (int)f;    }     reverse(out, p);    if (fi != -1) {        *p++ = '.';        *p++ = fi + '0';        *p = 0;    }    while (out[0] == '0' && out[1] != '.') {        size_t i;        for (i = 0; out[i] != 0; i++) {            out[i] = out[i + 1];        }    }    if (*out == '.') {        reverse(out, p);        *p++ = '0';        *p = 0;        reverse(out, p);    }    return makeQuaterImaginary(out);} ////////////////////////////////////////////////////// int main() {    char buffer[16];    int i;     for (i = 1; i <= 16; i++) {        struct Complex c1 = { i, 0.0 };        struct QuaterImaginary qi = c2qi(c1, buffer);        struct Complex c2 = qi2c(qi);        printComplex(c1);        printf(" -> ");        printQuaterImaginary(qi);        printf(" -> ");        printComplex(c2);         printf("     ");         c1 = negComplex(c1);        qi = c2qi(c1, buffer);        c2 = qi2c(qi);        printComplex(c1);        printf(" -> ");        printQuaterImaginary(qi);        printf(" -> ");        printComplex(c2);         printf("\n");    }     printf("\n");     for (i = 1; i <= 16; i++) {        struct Complex c1 = { 0.0, i };        struct QuaterImaginary qi = c2qi(c1, buffer);        struct Complex c2 = qi2c(qi);        printComplex(c1);        printf(" -> ");        printQuaterImaginary(qi);        printf(" -> ");        printComplex(c2);         printf("     ");         c1 = negComplex(c1);        qi = c2qi(c1, buffer);        c2 = qi2c(qi);        printComplex(c1);        printf(" -> ");        printQuaterImaginary(qi);        printf(" -> ");        printComplex(c2);         printf("\n");    }     return 0;}`
Output:
```(  1 +   0i) ->        1 -> (  1 +   0i)     ( -1 +  -0i) ->      103 -> ( -1 +   0i)
(  2 +   0i) ->        2 -> (  2 +   0i)     ( -2 +  -0i) ->      102 -> ( -2 +   0i)
(  3 +   0i) ->        3 -> (  3 +   0i)     ( -3 +  -0i) ->      101 -> ( -3 +   0i)
(  4 +   0i) ->    10300 -> (  4 +   0i)     ( -4 +  -0i) ->      100 -> ( -4 +   0i)
(  5 +   0i) ->    10301 -> (  5 +   0i)     ( -5 +  -0i) ->      203 -> ( -5 +   0i)
(  6 +   0i) ->    10302 -> (  6 +   0i)     ( -6 +  -0i) ->      202 -> ( -6 +   0i)
(  7 +   0i) ->    10303 -> (  7 +   0i)     ( -7 +  -0i) ->      201 -> ( -7 +   0i)
(  8 +   0i) ->    10200 -> (  8 +   0i)     ( -8 +  -0i) ->      200 -> ( -8 +   0i)
(  9 +   0i) ->    10201 -> (  9 +   0i)     ( -9 +  -0i) ->      303 -> ( -9 +   0i)
( 10 +   0i) ->    10202 -> ( 10 +   0i)     (-10 +  -0i) ->      302 -> (-10 +   0i)
( 11 +   0i) ->    10203 -> ( 11 +   0i)     (-11 +  -0i) ->      301 -> (-11 +   0i)
( 12 +   0i) ->    10100 -> ( 12 +   0i)     (-12 +  -0i) ->      300 -> (-12 +   0i)
( 13 +   0i) ->    10101 -> ( 13 +   0i)     (-13 +  -0i) ->  1030003 -> (-13 +   0i)
( 14 +   0i) ->    10102 -> ( 14 +   0i)     (-14 +  -0i) ->  1030002 -> (-14 +   0i)
( 15 +   0i) ->    10103 -> ( 15 +   0i)     (-15 +  -0i) ->  1030001 -> (-15 +   0i)
( 16 +   0i) ->    10000 -> ( 16 +   0i)     (-16 +  -0i) ->  1030000 -> (-16 +   0i)

(  0 +   1i) ->     10.2 -> (  0 +   1i)     ( -0 +  -1i) ->      0.2 -> (  0 +  -1i)
(  0 +   2i) ->     10.0 -> (  0 +   2i)     ( -0 +  -2i) ->   1030.0 -> (  0 +  -2i)
(  0 +   3i) ->     20.2 -> (  0 +   3i)     ( -0 +  -3i) ->   1030.2 -> (  0 +  -3i)
(  0 +   4i) ->     20.0 -> (  0 +   4i)     ( -0 +  -4i) ->   1020.0 -> (  0 +  -4i)
(  0 +   5i) ->     30.2 -> (  0 +   5i)     ( -0 +  -5i) ->   1020.2 -> (  0 +  -5i)
(  0 +   6i) ->     30.0 -> (  0 +   6i)     ( -0 +  -6i) ->   1010.0 -> (  0 +  -6i)
(  0 +   7i) -> 103000.2 -> (  0 +   7i)     ( -0 +  -7i) ->   1010.2 -> (  0 +  -7i)
(  0 +   8i) -> 103000.0 -> (  0 +   8i)     ( -0 +  -8i) ->   1000.0 -> (  0 +  -8i)
(  0 +   9i) -> 103010.2 -> (  0 +   9i)     ( -0 +  -9i) ->   1000.2 -> (  0 +  -9i)
(  0 +  10i) -> 103010.0 -> (  0 +  10i)     ( -0 + -10i) ->   2030.0 -> (  0 + -10i)
(  0 +  11i) -> 103020.2 -> (  0 +  11i)     ( -0 + -11i) ->   2030.2 -> (  0 + -11i)
(  0 +  12i) -> 103020.0 -> (  0 +  12i)     ( -0 + -12i) ->   2020.0 -> (  0 + -12i)
(  0 +  13i) -> 103030.2 -> (  0 +  13i)     ( -0 + -13i) ->   2020.2 -> (  0 + -13i)
(  0 +  14i) -> 103030.0 -> (  0 +  14i)     ( -0 + -14i) ->   2010.0 -> (  0 + -14i)
(  0 +  15i) -> 102000.2 -> (  0 +  15i)     ( -0 + -15i) ->   2010.2 -> (  0 + -15i)
(  0 +  16i) -> 102000.0 -> (  0 +  16i)     ( -0 + -16i) ->   2000.0 -> (  0 + -16i)```

C#

`using System;using System.Linq;using System.Text; namespace ImaginaryBaseNumbers {    class Complex {        private double real, imag;         public Complex(int r, int i) {            real = r;            imag = i;        }         public Complex(double r, double i) {            real = r;            imag = i;        }         public static Complex operator -(Complex self) =>            new Complex(-self.real, -self.imag);         public static Complex operator +(Complex rhs, Complex lhs) =>            new Complex(rhs.real + lhs.real, rhs.imag + lhs.imag);         public static Complex operator -(Complex rhs, Complex lhs) =>            new Complex(rhs.real - lhs.real, rhs.imag - lhs.imag);         public static Complex operator *(Complex rhs, Complex lhs) =>            new Complex(                rhs.real * lhs.real - rhs.imag * lhs.imag,                rhs.real * lhs.imag + rhs.imag * lhs.real                );         public static Complex operator *(Complex rhs, double lhs) =>             new Complex(rhs.real * lhs, rhs.imag * lhs);         public static Complex operator /(Complex rhs, Complex lhs) =>            rhs * lhs.Inv();         public Complex Inv() {            double denom = real * real + imag * imag;            return new Complex(real / denom, -imag / denom);        }         public QuaterImaginary ToQuaterImaginary() {            if (real == 0.0 && imag == 0.0) return new QuaterImaginary("0");            int re = (int)real;            int im = (int)imag;            int fi = -1;            StringBuilder sb = new StringBuilder();            while (re != 0) {                int rem = re % -4;                re /= -4;                if (rem < 0) {                    rem = 4 + rem;                    re++;                }                sb.Append(rem);                sb.Append(0);            }            if (im != 0) {                double f = (new Complex(0.0, imag) / new Complex(0.0, 2.0)).real;                im = (int)Math.Ceiling(f);                f = -4.0 * (f - im);                int index = 1;                while (im != 0) {                    int rem = im % -4;                    im /= -4;                    if (rem < 0) {                        rem = 4 + rem;                        im++;                    }                    if (index < sb.Length) {                        sb[index] = (char)(rem + 48);                    } else {                        sb.Append(0);                        sb.Append(rem);                    }                    index += 2;                }                fi = (int)f;            }            string reverse = new string(sb.ToString().Reverse().ToArray());            sb.Length = 0;            sb.Append(reverse);            if (fi != -1) sb.AppendFormat(".{0}", fi);            string s = sb.ToString().TrimStart('0');            if (s[0] == '.') s = "0" + s;            return new QuaterImaginary(s);        }         public override string ToString() {            double real2 = (real == -0.0) ? 0.0 : real;  // get rid of negative zero            double imag2 = (imag == -0.0) ? 0.0 : imag;  // ditto            if (imag2 == 0.0) {                return string.Format("{0}", real2);            }            if (real2 == 0.0) {                return string.Format("{0}i", imag2);            }            if (imag2 > 0.0) {                return string.Format("{0} + {1}i", real2, imag2);            }            return string.Format("{0} - {1}i", real2, -imag2);        }    }     class QuaterImaginary {        internal static Complex twoI = new Complex(0.0, 2.0);        internal static Complex invTwoI = twoI.Inv();         private string b2i;         public QuaterImaginary(string b2i) {            if (b2i == "" || !b2i.All(c => "0123.".IndexOf(c) > -1) || b2i.Count(c => c == '.') > 1) {                throw new Exception("Invalid Base 2i number");            }            this.b2i = b2i;        }         public Complex ToComplex() {            int pointPos = b2i.IndexOf(".");            int posLen = (pointPos != -1) ? pointPos : b2i.Length;            Complex sum = new Complex(0.0, 0.0);            Complex prod = new Complex(1.0, 0.0);            for (int j = 0; j < posLen; j++) {                double k = (b2i[posLen - 1 - j] - '0');                if (k > 0.0) {                    sum += prod * k;                }                prod *= twoI;            }            if (pointPos != -1) {                prod = invTwoI;                for (int j = posLen + 1; j < b2i.Length; j++) {                    double k = (b2i[j] - '0');                    if (k > 0.0) {                        sum += prod * k;                    }                    prod *= invTwoI;                }            }             return sum;        }         public override string ToString() {            return b2i;        }    }     class Program {        static void Main(string[] args) {            for (int i = 1; i <= 16; i++) {                Complex c1 = new Complex(i, 0);                QuaterImaginary qi = c1.ToQuaterImaginary();                Complex c2 = qi.ToComplex();                Console.Write("{0,4} -> {1,8} -> {2,4}     ", c1, qi, c2);                c1 = -c1;                qi = c1.ToQuaterImaginary();                c2 = qi.ToComplex();                Console.WriteLine("{0,4} -> {1,8} -> {2,4}", c1, qi, c2);            }            Console.WriteLine();            for (int i = 1; i <= 16; i++) {                Complex c1 = new Complex(0, i);                QuaterImaginary qi = c1.ToQuaterImaginary();                Complex c2 = qi.ToComplex();                Console.Write("{0,4} -> {1,8} -> {2,4}     ", c1, qi, c2);                c1 = -c1;                qi = c1.ToQuaterImaginary();                c2 = qi.ToComplex();                Console.WriteLine("{0,4} -> {1,8} -> {2,4}", c1, qi, c2);            }        }    }}`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i      -1i ->      0.2 ->  -1i
2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
3i ->     20.2 ->   3i      -3i ->   1030.2 ->  -3i
4i ->     20.0 ->   4i      -4i ->   1020.0 ->  -4i
5i ->     30.2 ->   5i      -5i ->   1020.2 ->  -5i
6i ->     30.0 ->   6i      -6i ->   1010.0 ->  -6i
7i -> 103000.2 ->   7i      -7i ->   1010.2 ->  -7i
8i -> 103000.0 ->   8i      -8i ->   1000.0 ->  -8i
9i -> 103010.2 ->   9i      -9i ->   1000.2 ->  -9i
10i -> 103010.0 ->  10i     -10i ->   2030.0 -> -10i
11i -> 103020.2 ->  11i     -11i ->   2030.2 -> -11i
12i -> 103020.0 ->  12i     -12i ->   2020.0 -> -12i
13i -> 103030.2 ->  13i     -13i ->   2020.2 -> -13i
14i -> 103030.0 ->  14i     -14i ->   2010.0 -> -14i
15i -> 102000.2 ->  15i     -15i ->   2010.2 -> -15i
16i -> 102000.0 ->  16i     -16i ->   2000.0 -> -16i```

C++

Translation of: C#
`#include <algorithm>#include <complex>#include <iomanip>#include <iostream> std::complex<double> inv(const std::complex<double>& c) {    double denom = c.real() * c.real() + c.imag() * c.imag();    return std::complex<double>(c.real() / denom, -c.imag() / denom);} class QuaterImaginary {public:    QuaterImaginary(const std::string& s) : b2i(s) {        static std::string base("0123.");         if (b2i.empty()            || std::any_of(s.cbegin(), s.cend(), [](char c) { return base.find(c) == std::string::npos; })            || std::count(s.cbegin(), s.cend(), '.') > 1) {            throw std::runtime_error("Invalid base 2i number");        }    }     QuaterImaginary& operator=(const QuaterImaginary& q) {        b2i = q.b2i;        return *this;    }     std::complex<double> toComplex() const {        int pointPos = b2i.find('.');        int posLen = (pointPos != std::string::npos) ? pointPos : b2i.length();        std::complex<double> sum(0.0, 0.0);        std::complex<double> prod(1.0, 0.0);        for (int j = 0; j < posLen; j++) {            double k = (b2i[posLen - 1 - j] - '0');            if (k > 0.0) {                sum += prod * k;            }            prod *= twoI;        }        if (pointPos != -1) {            prod = invTwoI;            for (size_t j = posLen + 1; j < b2i.length(); j++) {                double k = (b2i[j] - '0');                if (k > 0.0) {                    sum += prod * k;                }                prod *= invTwoI;            }        }         return sum;    }     friend std::ostream& operator<<(std::ostream&, const QuaterImaginary&); private:    const std::complex<double> twoI{ 0.0, 2.0 };    const std::complex<double> invTwoI = inv(twoI);     std::string b2i;}; std::ostream& operator<<(std::ostream& os, const QuaterImaginary& q) {    return os << q.b2i;} // only works properly if 'real' and 'imag' are both integralQuaterImaginary toQuaterImaginary(const std::complex<double>& c) {    if (c.real() == 0.0 && c.imag() == 0.0) return QuaterImaginary("0");     int re = (int)c.real();    int im = (int)c.imag();    int fi = -1;    std::stringstream ss;    while (re != 0) {        int rem = re % -4;        re /= -4;        if (rem < 0) {            rem = 4 + rem;            re++;        }        ss << rem << 0;    }    if (im != 0) {        double f = (std::complex<double>(0.0, c.imag()) / std::complex<double>(0.0, 2.0)).real();        im = (int)ceil(f);        f = -4.0 * (f - im);        size_t index = 1;        while (im != 0) {            int rem = im % -4;            im /= -4;            if (rem < 0) {                rem = 4 + rem;                im++;            }            if (index < ss.str().length()) {                ss.str()[index] = (char)(rem + 48);            } else {                ss << 0 << rem;            }            index += 2;        }        fi = (int)f;    }     auto r = ss.str();    std::reverse(r.begin(), r.end());    ss.str("");    ss.clear();    ss << r;    if (fi != -1) ss << '.' << fi;    r = ss.str();    r.erase(r.begin(), std::find_if(r.begin(), r.end(), [](char c) { return c != '0'; }));    if (r[0] == '.')r = "0" + r;    return QuaterImaginary(r);} int main() {    using namespace std;     for (int i = 1; i <= 16; i++) {        complex<double> c1(i, 0);        QuaterImaginary qi = toQuaterImaginary(c1);        complex<double> c2 = qi.toComplex();        cout << setw(8) << c1 << " -> " << setw(8) << qi << " -> " << setw(8) << c2 << "     ";        c1 = -c1;        qi = toQuaterImaginary(c1);        c2 = qi.toComplex();        cout << setw(8) << c1 << " -> " << setw(8) << qi << " -> " << setw(8) << c2 << endl;    }    cout << endl;     for (int i = 1; i <= 16; i++) {        complex<double> c1(0, i);        QuaterImaginary qi = toQuaterImaginary(c1);        complex<double> c2 = qi.toComplex();        cout << setw(8) << c1 << " -> " << setw(8) << qi << " -> " << setw(8) << c2 << "     ";        c1 = -c1;        qi = toQuaterImaginary(c1);        c2 = qi.toComplex();        cout << setw(8) << c1 << " -> " << setw(8) << qi << " -> " << setw(8) << c2 << endl;    }     return 0;}`
Output:
```   (1,0) ->        1 ->    (1,0)      (-1,-0) ->      103 ->   (-1,0)
(2,0) ->        2 ->    (2,0)      (-2,-0) ->      102 ->   (-2,0)
(3,0) ->        3 ->    (3,0)      (-3,-0) ->      101 ->   (-3,0)
(4,0) ->    10300 ->    (4,0)      (-4,-0) ->      100 ->   (-4,0)
(5,0) ->    10301 ->    (5,0)      (-5,-0) ->      203 ->   (-5,0)
(6,0) ->    10302 ->    (6,0)      (-6,-0) ->      202 ->   (-6,0)
(7,0) ->    10303 ->    (7,0)      (-7,-0) ->      201 ->   (-7,0)
(8,0) ->    10200 ->    (8,0)      (-8,-0) ->      200 ->   (-8,0)
(9,0) ->    10201 ->    (9,0)      (-9,-0) ->      303 ->   (-9,0)
(10,0) ->    10202 ->   (10,0)     (-10,-0) ->      302 ->  (-10,0)
(11,0) ->    10203 ->   (11,0)     (-11,-0) ->      301 ->  (-11,0)
(12,0) ->    10100 ->   (12,0)     (-12,-0) ->      300 ->  (-12,0)
(13,0) ->    10101 ->   (13,0)     (-13,-0) ->  1030003 ->  (-13,0)
(14,0) ->    10102 ->   (14,0)     (-14,-0) ->  1030002 ->  (-14,0)
(15,0) ->    10103 ->   (15,0)     (-15,-0) ->  1030001 ->  (-15,0)
(16,0) ->    10000 ->   (16,0)     (-16,-0) ->  1030000 ->  (-16,0)

(0,1) ->     10.2 ->    (0,1)      (-0,-1) ->      0.2 ->   (0,-1)
(0,2) ->     10.0 ->    (0,2)      (-0,-2) ->   1030.0 ->   (0,-2)
(0,3) ->     20.2 ->    (0,3)      (-0,-3) ->   1030.2 ->   (0,-3)
(0,4) ->     20.0 ->    (0,4)      (-0,-4) ->   1020.0 ->   (0,-4)
(0,5) ->     30.2 ->    (0,5)      (-0,-5) ->   1020.2 ->   (0,-5)
(0,6) ->     30.0 ->    (0,6)      (-0,-6) ->   1010.0 ->   (0,-6)
(0,7) -> 103000.2 ->    (0,7)      (-0,-7) ->   1010.2 ->   (0,-7)
(0,8) -> 103000.0 ->    (0,8)      (-0,-8) ->   1000.0 ->   (0,-8)
(0,9) -> 103010.2 ->    (0,9)      (-0,-9) ->   1000.2 ->   (0,-9)
(0,10) -> 103010.0 ->   (0,10)     (-0,-10) ->   2030.0 ->  (0,-10)
(0,11) -> 103020.2 ->   (0,11)     (-0,-11) ->   2030.2 ->  (0,-11)
(0,12) -> 103020.0 ->   (0,12)     (-0,-12) ->   2020.0 ->  (0,-12)
(0,13) -> 103030.2 ->   (0,13)     (-0,-13) ->   2020.2 ->  (0,-13)
(0,14) -> 103030.0 ->   (0,14)     (-0,-14) ->   2010.0 ->  (0,-14)
(0,15) -> 102000.2 ->   (0,15)     (-0,-15) ->   2010.2 ->  (0,-15)
(0,16) -> 102000.0 ->   (0,16)     (-0,-16) ->   2000.0 ->  (0,-16)```

D

Translation of: Kotlin
`import std.algorithm;import std.array;import std.complex;import std.conv;import std.format;import std.math;import std.stdio;import std.string; Complex!double inv(Complex!double v) {    auto denom = v.re*v.re + v.im*v.im;    return v.conj / denom;} QuaterImaginary toQuaterImaginary(Complex!double v) {    if (v.re == 0.0 && v.im == 0.0) return QuaterImaginary("0");    auto re = v.re.to!int;    auto im = v.im.to!int;    auto fi = -1;    auto sb = appender!(char[]);    while (re != 0) {        auto rem = re % -4;        re /= -4;        if (rem < 0) {            rem = 4 + rem;            re++;        }        sb.formattedWrite("%d", rem);        sb.put("0");    }    if (im != 0) {        auto f = (complex(0.0, v.im) / complex(0.0, 2.0)).re;        im = f.ceil.to!int;        f = -4.0 * (f - im.to!double);        auto index = 1;        while (im != 0) {            auto rem = im % -4;            im /= -4;            if (rem < 0) {                rem = 4 + rem;                im++;            }            if (index < sb.data.length) {                sb.data[index] = cast(char)(rem + '0');            } else {                sb.put("0");                sb.formattedWrite("%d", rem);            }            index += 2;        }        fi = f.to!int;    }    sb.data.reverse;    if (fi != -1) sb.formattedWrite(".%d", fi);    int i;    while (i < sb.data.length && sb.data[i] == '0') {        i++;    }    auto s = sb.data[i..\$].idup;    if (s[0] == '.') s = "0" ~ s;    return QuaterImaginary(s);} struct QuaterImaginary {    private string b2i;     this(string b2i) {        if (b2i == "" || b2i.count('.') > 1) {            throw new Exception("Invalid Base 2i number");        }        foreach (c; b2i) {            if (!canFind("0123.", c)) {                throw new Exception("Invalid Base 2i number");            }        }        this.b2i = b2i;    }     T opCast(T : Complex!double)() {        auto pointPos = b2i.indexOf('.');        size_t posLen;        if (pointPos != -1) {            posLen = pointPos;        } else {            posLen = b2i.length;        }        auto sum = complex(0.0, 0.0);        auto prod = complex(1.0, 0.0);        foreach (j; 0..posLen) {            auto k = (b2i[posLen - 1 - j] - '0').to!double;            if (k > 0.0) {                sum += prod * k;            }            prod *= twoI;        }        if (pointPos != -1) {            prod = invTwoI;            foreach (j; posLen+1..b2i.length) {                auto k = (b2i[j] - '0').to!double;                if (k > 0.0) {                    sum += prod * k;                }                prod *= invTwoI;            }        }        return sum;    }     void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const {        if (fmt.spec == 's') {            for (int i=0; i<fmt.width-b2i.length; ++i) {                sink(" ");            }        }        sink(b2i);    }     enum twoI = complex(0.0, 2.0);    enum invTwoI = twoI.inv;} unittest {    import std.exception;    assertThrown!Exception(QuaterImaginary(""));    assertThrown!Exception(QuaterImaginary("1.2.3"));    assertThrown!Exception(QuaterImaginary("a"));    assertThrown!Exception(QuaterImaginary("4"));    assertThrown!Exception(QuaterImaginary(" "));} void main() {    foreach (i; 1..17) {        auto c1 = complex(i, 0);        auto qi = c1.toQuaterImaginary;        auto c2 = cast(Complex!double) qi;        writef("%4s -> %8s -> %4s     ", c1.re, qi, c2.re);        c1 = -c1;        qi = c1.toQuaterImaginary();        c2 = cast(Complex!double) qi;        writefln("%4s -> %8s -> %4s", c1.re, qi, c2.re);    }    writeln;    foreach (i; 1..17) {        auto c1 = complex(0, i);        auto qi = c1.toQuaterImaginary;        auto c2 = qi.to!(Complex!double);        writef("%4si -> %8s -> %4si     ", c1.im, qi, c2.im);        c1 = -c1;        qi = c1.toQuaterImaginary();        c2 = cast(Complex!double) qi;        writefln("%4si -> %8s -> %4si", c1.im, qi, c2.im);    }}`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i      -1i ->      0.2 ->  -1i
2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
3i ->     20.2 ->   3i      -3i ->   1030.2 ->  -3i
4i ->     20.0 ->   4i      -4i ->   1020.0 ->  -4i
5i ->     30.2 ->   5i      -5i ->   1020.2 ->  -5i
6i ->     30.0 ->   6i      -6i ->   1010.0 ->  -6i
7i -> 103000.2 ->   7i      -7i ->   1010.2 ->  -7i
8i -> 103000.0 ->   8i      -8i ->   1000.0 ->  -8i
9i -> 103010.2 ->   9i      -9i ->   1000.2 ->  -9i
10i -> 103010.0 ->  10i     -10i ->   2030.0 -> -10i
11i -> 103020.2 ->  11i     -11i ->   2030.2 -> -11i
12i -> 103020.0 ->  12i     -12i ->   2020.0 -> -12i
13i -> 103030.2 ->  13i     -13i ->   2020.2 -> -13i
14i -> 103030.0 ->  14i     -14i ->   2010.0 -> -14i
15i -> 102000.2 ->  15i     -15i ->   2010.2 -> -15i
16i -> 102000.0 ->  16i     -16i ->   2000.0 -> -16i```

Go

Translation of: Kotlin

... though a bit shorter as Go has support for complex numbers built into the language.

`package main import (    "fmt"    "math"    "strconv"    "strings") const (    twoI    = 2.0i    invTwoI = 1.0 / twoI) type quaterImaginary struct {    b2i string} func reverse(s string) string {    r := []rune(s)    for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {        r[i], r[j] = r[j], r[i]    }    return string(r)} func newQuaterImaginary(b2i string) quaterImaginary {    b2i = strings.TrimSpace(b2i)    _, err := strconv.ParseFloat(b2i, 64)    if err != nil {        panic("invalid Base 2i number")    }    return quaterImaginary{b2i}} func toComplex(q quaterImaginary) complex128 {    pointPos := strings.Index(q.b2i, ".")    var posLen int    if pointPos != -1 {        posLen = pointPos    } else {        posLen = len(q.b2i)    }    sum := 0.0i    prod := complex(1.0, 0.0)    for j := 0; j < posLen; j++ {        k := float64(q.b2i[posLen-1-j] - '0')        if k > 0.0 {            sum += prod * complex(k, 0.0)        }        prod *= twoI    }    if pointPos != -1 {        prod = invTwoI        for j := posLen + 1; j < len(q.b2i); j++ {            k := float64(q.b2i[j] - '0')            if k > 0.0 {                sum += prod * complex(k, 0.0)            }            prod *= invTwoI        }    }    return sum} func (q quaterImaginary) String() string {    return q.b2i} // only works properly if 'real' and 'imag' are both integralfunc toQuaterImaginary(c complex128) quaterImaginary {    if c == 0i {        return quaterImaginary{"0"}    }    re := int(real(c))    im := int(imag(c))    fi := -1    var sb strings.Builder    for re != 0 {        rem := re % -4        re /= -4        if rem < 0 {            rem += 4            re++        }        sb.WriteString(strconv.Itoa(rem))        sb.WriteString("0")    }    if im != 0 {        f := real(complex(0.0, imag(c)) / 2.0i)        im = int(math.Ceil(f))        f = -4.0 * (f - float64(im))        index := 1        for im != 0 {            rem := im % -4            im /= -4            if rem < 0 {                rem += 4                im++            }            if index < sb.Len() {                bs := []byte(sb.String())                bs[index] = byte(rem + 48)                sb.Reset()                sb.Write(bs)            } else {                sb.WriteString("0")                sb.WriteString(strconv.Itoa(rem))            }            index += 2        }        fi = int(f)    }    s := reverse(sb.String())    if fi != -1 {        s = fmt.Sprintf("%s.%d", s, fi)    }    s = strings.TrimLeft(s, "0")    if s[0] == '.' {        s = "0" + s    }    return newQuaterImaginary(s)} func main() {    for i := 1; i <= 16; i++ {        c1 := complex(float64(i), 0.0)        qi := toQuaterImaginary(c1)        c2 := toComplex(qi)        fmt.Printf("%4.0f -> %8s -> %4.0f     ", real(c1), qi, real(c2))        c1 = -c1        qi = toQuaterImaginary(c1)        c2 = toComplex(qi)        fmt.Printf("%4.0f -> %8s -> %4.0f\n", real(c1), qi, real(c2))    }    fmt.Println()    for i := 1; i <= 16; i++ {        c1 := complex(0.0, float64(i))        qi := toQuaterImaginary(c1)        c2 := toComplex(qi)        fmt.Printf("%3.0fi -> %8s -> %3.0fi     ", imag(c1), qi, imag(c2))        c1 = -c1        qi = toQuaterImaginary(c1)        c2 = toComplex(qi)        fmt.Printf("%3.0fi -> %8s -> %3.0fi\n", imag(c1), qi, imag(c2))    }}`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i      -1i ->      0.2 ->  -1i
2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
3i ->     20.2 ->   3i      -3i ->   1030.2 ->  -3i
4i ->     20.0 ->   4i      -4i ->   1020.0 ->  -4i
5i ->     30.2 ->   5i      -5i ->   1020.2 ->  -5i
6i ->     30.0 ->   6i      -6i ->   1010.0 ->  -6i
7i -> 103000.2 ->   7i      -7i ->   1010.2 ->  -7i
8i -> 103000.0 ->   8i      -8i ->   1000.0 ->  -8i
9i -> 103010.2 ->   9i      -9i ->   1000.2 ->  -9i
10i -> 103010.0 ->  10i     -10i ->   2030.0 -> -10i
11i -> 103020.2 ->  11i     -11i ->   2030.2 -> -11i
12i -> 103020.0 ->  12i     -12i ->   2020.0 -> -12i
13i -> 103030.2 ->  13i     -13i ->   2020.2 -> -13i
14i -> 103030.0 ->  14i     -14i ->   2010.0 -> -14i
15i -> 102000.2 ->  15i     -15i ->   2010.2 -> -15i
16i -> 102000.0 ->  16i     -16i ->   2000.0 -> -16i
```

Haskell

`import Data.Char (chr, digitToInt, intToDigit, isDigit, ord)import Data.Complex (Complex(..), imagPart, realPart)import Data.List (elemIndex, delete)import Data.Maybe (fromMaybe)  base :: Complex Floatbase = 0 :+ 2 quotRemPositive :: Int -> Int -> (Int, Int)quotRemPositive a b  | r < 0 = (1 + q, floor (realPart (-base ^^ 2)) + r)  | otherwise = (q, r)  where    (q, r) = quotRem a b digitToIntQI :: Char -> IntdigitToIntQI c  | isDigit c = digitToInt c  | otherwise = ord c - ord 'a' + 10 shiftRight :: String -> StringshiftRight n  | l == '0' = h  | otherwise = h ++ "." ++ [l]  where    (l, h) = (last n, init n) intToDigitQI :: Int -> CharintToDigitQI i  | i `elem` [0 .. 9] = intToDigit i  | otherwise = chr (i - 10 + ord 'a') fromQItoComplex :: String -> Complex Float -> Complex FloatfromQItoComplex num b =  let dot = fromMaybe (length num) (elemIndex '.' num)  in fst \$     foldl       (\(a, indx) x ->           (a + fromIntegral (digitToIntQI x) * (b ^^ (dot - indx)), indx + 1))       (0, 1)       (delete '.' num) euclidEr :: Int -> Int -> [Int] -> [Int]euclidEr a b l  | a == 0 = l  | otherwise =    let (q, r) = quotRemPositive a b    in euclidEr q b (0 : r : l) fromIntToQI :: Int -> [Int]fromIntToQI 0 = [0]fromIntToQI x = tail (euclidEr x (floor \$ realPart (base ^^ 2)) []) getCuid :: Complex Int -> IntgetCuid c = imagPart c * floor (imagPart (-base)) qizip :: Complex Int -> [Int]qizip c =  let (r, i) = (fromIntToQI (realPart c) ++ [0], fromIntToQI (getCuid c))  in let m = min (length r) (length i)     in take (length r - m) r ++        take (length i - m) i ++        reverse (zipWith (+) (take m (reverse r)) (take m (reverse i))) fromComplexToQI :: Complex Int -> StringfromComplexToQI = shiftRight . fmap intToDigitQI . qizip main :: IO ()main = print (fromComplexToQI (35 :+ 23)) >> print (fromQItoComplex "10.2" base)`
Output:
```"121003.2"
0.0 :+ 1.0
```

With base = 8i (you may choose any base):

```"3z.8"
0.0 :+ 7.75```

Java

Translation of: Kotlin
`public class ImaginaryBaseNumber {    private static class Complex {        private Double real, imag;         public Complex(double r, double i) {            this.real = r;            this.imag = i;        }         public Complex(int r, int i) {            this.real = (double) r;            this.imag = (double) i;        }         public Complex add(Complex rhs) {            return new Complex(                real + rhs.real,                imag + rhs.imag            );        }         public Complex times(Complex rhs) {            return new Complex(                real * rhs.real - imag * rhs.imag,                real * rhs.imag + imag * rhs.real            );        }         public Complex times(double rhs) {            return new Complex(                real * rhs,                imag * rhs            );        }         public Complex inv() {            double denom = real * real + imag * imag;            return new Complex(                real / denom,                -imag / denom            );        }         public Complex unaryMinus() {            return new Complex(-real, -imag);        }         public Complex divide(Complex rhs) {            return this.times(rhs.inv());        }         // only works properly if 'real' and 'imag' are both integral        public QuaterImaginary toQuaterImaginary() {            if (real == 0.0 && imag == 0.0) return new QuaterImaginary("0");            int re = real.intValue();            int im = imag.intValue();            int fi = -1;            StringBuilder sb = new StringBuilder();            while (re != 0) {                int rem = re % -4;                re /= -4;                if (rem < 0) {                    rem += 4;                    re++;                }                sb.append(rem);                sb.append(0);            }            if (im != 0) {                Double f = new Complex(0.0, imag).divide(new Complex(0.0, 2.0)).real;                im = ((Double) Math.ceil(f)).intValue();                f = -4.0 * (f - im);                int index = 1;                while (im != 0) {                    int rem = im % -4;                    im /= -4;                    if (rem < 0) {                        rem += 4;                        im++;                    }                    if (index < sb.length()) {                        sb.setCharAt(index, (char) (rem + 48));                    } else {                        sb.append(0);                        sb.append(rem);                    }                    index += 2;                }                fi = f.intValue();            }            sb.reverse();            if (fi != -1) sb.append(".").append(fi);            while (sb.charAt(0) == '0') sb.deleteCharAt(0);            if (sb.charAt(0) == '.') sb.insert(0, '0');            return new QuaterImaginary(sb.toString());        }         @Override        public String toString() {            double real2 = real == -0.0 ? 0.0 : real;  // get rid of negative zero            double imag2 = imag == -0.0 ? 0.0 : imag;  // ditto            String result = imag2 >= 0.0 ? String.format("%.0f + %.0fi", real2, imag2) : String.format("%.0f - %.0fi", real2, -imag2);            result = result.replace(".0 ", " ").replace(".0i", "i").replace(" + 0i", "");            if (result.startsWith("0 + ")) result = result.substring(4);            if (result.startsWith("0 - ")) result = result.substring(4);            return result;        }    }     private static class QuaterImaginary {        private static final Complex TWOI = new Complex(0.0, 2.0);        private static final Complex INVTWOI = TWOI.inv();         private String b2i;         public QuaterImaginary(String b2i) {            if (b2i.equals("") || !b2i.chars().allMatch(c -> "0123.".indexOf(c) > -1) || b2i.chars().filter(c -> c == '.').count() > 1) {                throw new RuntimeException("Invalid Base 2i number");            }            this.b2i = b2i;        }         public Complex toComplex() {            int pointPos = b2i.indexOf(".");            int posLen = pointPos != -1 ? pointPos : b2i.length();            Complex sum = new Complex(0, 0);            Complex prod = new Complex(1, 0);             for (int j = 0; j < posLen; ++j) {                double k = b2i.charAt(posLen - 1 - j) - '0';                if (k > 0.0) sum = sum.add(prod.times(k));                prod = prod.times(TWOI);            }            if (pointPos != -1) {                prod = INVTWOI;                for (int j = posLen + 1; j < b2i.length(); ++j) {                    double k = b2i.charAt(j) - '0';                    if (k > 0.0) sum = sum.add(prod.times(k));                    prod = prod.times(INVTWOI);                }            }             return sum;        }         @Override        public String toString() {            return b2i;        }    }     public static void main(String[] args) {        String fmt = "%4s -> %8s -> %4s";        for (int i = 1; i <= 16; ++i) {            Complex c1 = new Complex(i, 0);            QuaterImaginary qi = c1.toQuaterImaginary();            Complex c2 = qi.toComplex();            System.out.printf(fmt + "     ", c1, qi, c2);            c1 = c2.unaryMinus();            qi = c1.toQuaterImaginary();            c2 = qi.toComplex();            System.out.printf(fmt, c1, qi, c2);            System.out.println();        }        System.out.println();        for (int i = 1; i <= 16; ++i) {            Complex c1 = new Complex(0, i);            QuaterImaginary qi = c1.toQuaterImaginary();            Complex c2 = qi.toComplex();            System.out.printf(fmt + "     ", c1, qi, c2);            c1 = c2.unaryMinus();            qi = c1.toQuaterImaginary();            c2 = qi.toComplex();            System.out.printf(fmt, c1, qi, c2);            System.out.println();        }    }}`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i       1i ->      0.2 ->   1i
2i ->     10.0 ->   2i       2i ->   1030.0 ->   2i
3i ->     20.2 ->   3i       3i ->   1030.2 ->   3i
4i ->     20.0 ->   4i       4i ->   1020.0 ->   4i
5i ->     30.2 ->   5i       5i ->   1020.2 ->   5i
6i ->     30.0 ->   6i       6i ->   1010.0 ->   6i
7i -> 103000.2 ->   7i       7i ->   1010.2 ->   7i
8i -> 103000.0 ->   8i       8i ->   1000.0 ->   8i
9i -> 103010.2 ->   9i       9i ->   1000.2 ->   9i
10i -> 103010.0 ->  10i      10i ->   2030.0 ->  10i
11i -> 103020.2 ->  11i      11i ->   2030.2 ->  11i
12i -> 103020.0 ->  12i      12i ->   2020.0 ->  12i
13i -> 103030.2 ->  13i      13i ->   2020.2 ->  13i
14i -> 103030.0 ->  14i      14i ->   2010.0 ->  14i
15i -> 102000.2 ->  15i      15i ->   2010.2 ->  15i
16i -> 102000.0 ->  16i      16i ->   2000.0 ->  16i```

Julia

Translation of: C#
`import Base.show, Base.parse, Base.+, Base.-, Base.*, Base./, Base.^ function inbase4(charvec::Vector)    if (!all(x -> x in ['-', '0', '1', '2', '3', '.'], charvec)) ||        ((x = findlast(x -> x == '-', charvec)) != nothing && x > findfirst(x -> x != '-', charvec)) ||        ((x = findall(x -> x == '.', charvec)) != nothing && length(x) > 1)        return false    end    trueendinbase4(s::String) = inbase4(split(s, "")) abstract type ImaginaryBaseNumber <: Number end struct QuaterImaginary <: ImaginaryBaseNumber    cvector::Vector{Char}    isnegative::Boolend function QuaterImaginary(charvec::Vector{Char})    isneg = false    if !inbase4(charvec)        throw("Constructor vector for QuaterImaginary (\$charvec) is not base 2i")    elseif (i = length(findall(x -> x == '-', charvec))) > 0        isneg = (-1) ^ i == -1    end    while length(charvec) > 1 && charvec[1] == '0' && charvec[2] != '.'        popfirst!(charvec)    end    if (i = findfirst(x -> x == '.', charvec)) != nothing        while length(charvec) > 3 && charvec[end] == '0' && charvec[end-1] != '.'            pop!(charvec)        end    end    if charvec[1] == '.'            pushfirst!(charvec, '0')    end    if charvec[end] == '.'        pop!(charvec)    end    QuaterImaginary(filter!(x -> x in ['0', '1', '2', '3', '.'], charvec), isneg)end function QuaterImaginary(s::String = "0")    if match(r"^-?[0123\.]+\$", s) == nothing        throw("String constructor argument <\$s> for QuaterImaginary is not base 2i")    end    QuaterImaginary([s[i] for i in 1:length(s)])end show(io::IO, qim::QuaterImaginary) = print(io, qim.isnegative ? "-" : "", join(qim.cvector, "")) function parse(QuaterImaginary, x::Complex)    sb = Vector{Char}()    rea, ima = Int(floor(real(x))), Int(floor(imag(x)))    if floor(real(x)) != rea || floor(imag(x)) != ima        throw("Non-integer real and complex portions of complex numbers are not supported for QuaterImaginary")    elseif rea == 0 == ima        return QuaterImaginary(['0'])    else        fi = -1        while rea != 0            rea, rem = divrem(rea, -4)            if rem < 0                rem += 4                rea += 1            end            push!(sb, Char(rem + '0'), '0')        end        if ima != 0            f = real((ima * im)/(2im))            ima = Int(ceil(f))            f = -4.0 * (f - ima)            idx = 1            while ima != 0                ima, rem = divrem(ima, -4)                if rem < 0                    rem += 4                    ima += 1                end                if idx < length(sb)                    sb[idx + 1] = Char(rem + '0')                else                    push!(sb, '0', Char(rem + '0'))                end                idx += 2            end            fi = Int(floor(f))        end        sb = reverse(sb)        if fi != -1            push!(sb, '.')            append!(sb, map(x -> x[1], split(string(fi), "")))        end    end    QuaterImaginary(sb)end function parse(Complex, qim::QuaterImaginary)    pointpos = ((x = indexin('.', qim.cvector))[1] == nothing) ? -1 : x[1]    poslen = (pointpos != -1) ? pointpos : length(qim.cvector) + 1    qsum = 0.0 + 0.0im    prod = 1.0 + 0.0im    for j in 1:poslen-1        k = Float64(qim.cvector[poslen - j] - '0')        if k > 0.0            qsum += prod * k        end        prod *= 2im    end    if pointpos != -1        prod = inv(2im)        for j in poslen+1:length(qim.cvector)            k = Float64(qim.cvector[j] - '0')            if k > 0.0                qsum += prod * k            end            prod *= inv(2im)        end    end    qsumend function testquim()    function printcqc(c)        q = parse(QuaterImaginary, Complex(c))        c2 = parse(Complex, q)        if imag(c2) == 0            c2 = Int(c2)        end        print(lpad(c, 10), " -> ", lpad(q, 10), " -> ", lpad(c2, 12))    end    for i in 1:16        printcqc(i)        print("       ")        printcqc(-i)        println()    end    println()    for i in 1:16        c1 = Complex(0, i)        printcqc(c1)        print("       ")        printcqc(-c1)        println()    endend QuaterImaginary(c::Complex) = parse(QuaterImaginary, c)Complex(q::QuaterImaginary) = parse(Complex, q) +(q1::QuaterImaginary, q2::QuaterImaginary) = QuaterImaginary(Complex(q1) + Complex(q2))+(q1::Complex, q2::QuaterImaginary) = q1 + Complex(q2)+(q1::QuaterImaginary, q2::Complex) = Complex(q1) + q2-(q1::QuaterImaginary, q2::QuaterImaginary) = QuaterImaginary(Complex(q1) - Complex(q2))-(q1::Complex, q2::QuaterImaginary) = q1 - Complex(q2)-(q1::QuaterImaginary, q2::Complex) = Complex(q1) - q2*(q1::QuaterImaginary, q2::QuaterImaginary) = QuaterImaginary(Complex(q1) * Complex(q2))*(q1::Complex, q2::QuaterImaginary) = q1 * Complex(q2)*(q1::QuaterImaginary, q2::Complex) = Complex(q1) * q2/(q1::QuaterImaginary, q2::QuaterImaginary) = QuaterImaginary(Complex(q1) / Complex(q2))/(q1::Complex, q2::QuaterImaginary) = q1 / Complex(q2)/(q1::QuaterImaginary, q2::Complex) = Complex(q1) / q2^(q1::QuaterImaginary, q2::QuaterImaginary) = QuaterImaginary(Complex(q1) ^ Complex(q2))^(q1::Complex, q2::QuaterImaginary) = q1 ^ Complex(q2)^(q1::QuaterImaginary, q2::Complex) = Complex(q1) ^ q2 testquim() `
Output:
```
1 ->          1 ->            1               -1 ->        103 ->           -1
2 ->          2 ->            2               -2 ->        102 ->           -2
3 ->          3 ->            3               -3 ->        101 ->           -3
4 ->      10300 ->            4               -4 ->        100 ->           -4
5 ->      10301 ->            5               -5 ->        203 ->           -5
6 ->      10302 ->            6               -6 ->        202 ->           -6
7 ->      10303 ->            7               -7 ->        201 ->           -7
8 ->      10200 ->            8               -8 ->        200 ->           -8
9 ->      10201 ->            9               -9 ->        303 ->           -9
10 ->      10202 ->           10              -10 ->        302 ->          -10
11 ->      10203 ->           11              -11 ->        301 ->          -11
12 ->      10100 ->           12              -12 ->        300 ->          -12
13 ->      10101 ->           13              -13 ->    1030003 ->          -13
14 ->      10102 ->           14              -14 ->    1030002 ->          -14
15 ->      10103 ->           15              -15 ->    1030001 ->          -15
16 ->      10000 ->           16              -16 ->    1030000 ->          -16

0 + 1im ->       10.2 ->  0.0 + 1.0im          0 - 1im ->        0.2 ->  0.0 - 1.0im
0 + 2im ->       10.0 ->  0.0 + 2.0im          0 - 2im ->     1030.0 ->  0.0 - 2.0im
0 + 3im ->       20.2 ->  0.0 + 3.0im          0 - 3im ->     1030.2 ->  0.0 - 3.0im
0 + 4im ->       20.0 ->  0.0 + 4.0im          0 - 4im ->     1020.0 ->  0.0 - 4.0im
0 + 5im ->       30.2 ->  0.0 + 5.0im          0 - 5im ->     1020.2 ->  0.0 - 5.0im
0 + 6im ->       30.0 ->  0.0 + 6.0im          0 - 6im ->     1010.0 ->  0.0 - 6.0im
0 + 7im ->   103000.2 ->  0.0 + 7.0im          0 - 7im ->     1010.2 ->  0.0 - 7.0im
0 + 8im ->   103000.0 ->  0.0 + 8.0im          0 - 8im ->     1000.0 ->  0.0 - 8.0im
0 + 9im ->   103010.2 ->  0.0 + 9.0im          0 - 9im ->     1000.2 ->  0.0 - 9.0im
0 + 10im ->   103010.0 -> 0.0 + 10.0im         0 - 10im ->     2030.0 -> 0.0 - 10.0im
0 + 11im ->   103020.2 -> 0.0 + 11.0im         0 - 11im ->     2030.2 -> 0.0 - 11.0im
0 + 12im ->   103020.0 -> 0.0 + 12.0im         0 - 12im ->     2020.0 -> 0.0 - 12.0im
0 + 13im ->   103030.2 -> 0.0 + 13.0im         0 - 13im ->     2020.2 -> 0.0 - 13.0im
0 + 14im ->   103030.0 -> 0.0 + 14.0im         0 - 14im ->     2010.0 -> 0.0 - 14.0im
0 + 15im ->   102000.2 -> 0.0 + 15.0im         0 - 15im ->     2010.2 -> 0.0 - 15.0im
0 + 16im ->   102000.0 -> 0.0 + 16.0im         0 - 16im ->     2000.0 -> 0.0 - 16.0im

```

Kotlin

The following deals with conversions to and from quater-imaginary only.

As the JDK lacks a complex number class, I've included a very basic one in the program.

`// version 1.2.10 import kotlin.math.ceil class Complex(val real: Double, val imag: Double) {     constructor(r: Int, i: Int) : this(r.toDouble(), i.toDouble())     operator fun plus(other: Complex) = Complex(real + other.real, imag + other.imag)     operator fun times(other: Complex) = Complex(        real * other.real - imag * other.imag,        real * other.imag + imag * other.real    )     operator fun times(other: Double) = Complex(real * other, imag * other)     fun inv(): Complex {        val denom = real * real + imag * imag        return Complex(real / denom, -imag / denom)    }     operator fun unaryMinus() = Complex(-real, -imag)     operator fun minus(other: Complex) = this + (-other)     operator fun div(other: Complex) = this * other.inv()     // only works properly if 'real' and 'imag' are both integral    fun toQuaterImaginary(): QuaterImaginary {        if (real == 0.0 && imag == 0.0) return QuaterImaginary("0")        var re = real.toInt()        var im = imag.toInt()        var fi = -1        val sb = StringBuilder()        while (re != 0) {            var rem = re % -4            re /= -4            if (rem < 0) {                rem = 4 + rem                re++            }            sb.append(rem)            sb.append(0)        }        if (im != 0) {            var f = (Complex(0.0, imag) / Complex(0.0, 2.0)).real            im = ceil(f).toInt()            f = -4.0 * (f - im.toDouble())            var index = 1            while (im != 0) {                var rem = im % -4                im /= -4                if (rem < 0) {                    rem = 4 + rem                    im++                }                if (index < sb.length) {                    sb[index] = (rem + 48).toChar()                }                else {                    sb.append(0)                    sb.append(rem)                }                index += 2            }            fi = f.toInt()        }        sb.reverse()        if (fi != -1) sb.append(".\$fi")        var s = sb.toString().trimStart('0')        if (s.startsWith(".")) s = "0\$s"        return QuaterImaginary(s)    }     override fun toString(): String {        val real2 = if (real == -0.0) 0.0 else real  // get rid of negative zero        val imag2 = if (imag == -0.0) 0.0 else imag  // ditto        var result = if (imag2 >= 0.0) "\$real2 + \${imag2}i" else "\$real2 - \${-imag2}i"        result = result.replace(".0 ", " ").replace(".0i", "i").replace(" + 0i", "")        if (result.startsWith("0 + ")) result = result.drop(4)        if (result.startsWith("0 - ")) result = "-" + result.drop(4)        return result    }} class QuaterImaginary(val b2i: String) {     init {        if (b2i == "" || !b2i.all { it in "0123." } || b2i.count { it == '.'} > 1 )            throw RuntimeException("Invalid Base 2i number")    }     fun toComplex(): Complex {        val pointPos = b2i.indexOf(".")        var posLen = if (pointPos != -1) pointPos else b2i.length        var sum = Complex(0.0, 0.0)        var prod = Complex(1.0, 0.0)        for (j in 0 until posLen) {            val k = (b2i[posLen - 1 - j] - '0').toDouble()            if (k > 0.0) sum += prod * k            prod *= twoI        }        if (pointPos != -1) {            prod = invTwoI            for (j in posLen + 1 until b2i.length) {                val k = (b2i[j] - '0').toDouble()                if (k > 0.0) sum += prod * k                prod *= invTwoI            }        }        return sum    }     override fun toString() = b2i     companion object {        val twoI = Complex(0.0, 2.0)        val invTwoI = twoI.inv()    }} fun main(args: Array<String>) {     val fmt = "%4s -> %8s -> %4s"       for (i in 1..16) {        var c1 = Complex(i, 0)        var qi = c1.toQuaterImaginary()        var c2 = qi.toComplex()        print("\$fmt     ".format(c1, qi, c2))        c1 = -c1        qi = c1.toQuaterImaginary()        c2 = qi.toComplex()        println(fmt.format(c1, qi, c2))    }    println()    for (i in 1..16) {        var c1 = Complex(0, i)        var qi = c1.toQuaterImaginary()        var c2 = qi.toComplex()        print("\$fmt     ".format(c1, qi, c2))        c1 = -c1        qi = c1.toQuaterImaginary()        c2 = qi.toComplex()        println(fmt.format(c1, qi, c2))    }}`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i      -1i ->      0.2 ->  -1i
2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
3i ->     20.2 ->   3i      -3i ->   1030.2 ->  -3i
4i ->     20.0 ->   4i      -4i ->   1020.0 ->  -4i
5i ->     30.2 ->   5i      -5i ->   1020.2 ->  -5i
6i ->     30.0 ->   6i      -6i ->   1010.0 ->  -6i
7i -> 103000.2 ->   7i      -7i ->   1010.2 ->  -7i
8i -> 103000.0 ->   8i      -8i ->   1000.0 ->  -8i
9i -> 103010.2 ->   9i      -9i ->   1000.2 ->  -9i
10i -> 103010.0 ->  10i     -10i ->   2030.0 -> -10i
11i -> 103020.2 ->  11i     -11i ->   2030.2 -> -11i
12i -> 103020.0 ->  12i     -12i ->   2020.0 -> -12i
13i -> 103030.2 ->  13i     -13i ->   2020.2 -> -13i
14i -> 103030.0 ->  14i     -14i ->   2010.0 -> -14i
15i -> 102000.2 ->  15i     -15i ->   2010.2 -> -15i
16i -> 102000.0 ->  16i     -16i ->   2000.0 -> -16i
```

Modula-2

Translation of: C#
`MODULE ImaginaryBase;FROM FormatString IMPORT FormatString;FROM RealMath IMPORT round;   FROM Terminal IMPORT WriteString,WriteLn,ReadChar; (* Helper *)TYPE    String = ARRAY[0..10] OF CHAR;    StringBuilder = RECORD        buf : String;        ptr : CARDINAL;    END; PROCEDURE ToChar(n : INTEGER) : CHAR;BEGIN    CASE n OF        0 : RETURN '0' |        1 : RETURN '1' |        2 : RETURN '2' |        3 : RETURN '3' |        4 : RETURN '4' |        5 : RETURN '5' |        6 : RETURN '6' |        7 : RETURN '7' |        8 : RETURN '8' |        9 : RETURN '9'    ELSE        RETURN '-'    ENDEND ToChar; PROCEDURE AppendChar(VAR sb : StringBuilder; c : CHAR);BEGIN            sb.buf[sb.ptr] := c;    INC(sb.ptr);    sb.buf[sb.ptr] := 0CEND AppendChar; PROCEDURE AppendInt(VAR sb : StringBuilder; n : INTEGER);BEGIN            sb.buf[sb.ptr] := ToChar(n);    INC(sb.ptr);    sb.buf[sb.ptr] := 0CEND AppendInt; PROCEDURE Ceil(r : REAL) : REAL;VAR t : REAL;BEGIN           t := FLOAT(INT(r));        IF r - t > 0.0 THEN        t := t + 1.0    END;    RETURN tEND Ceil; PROCEDURE Modulus(q,d : INTEGER) : INTEGER;VAR t : INTEGER;BEGIN    t := q / d;    RETURN q - d * tEND Modulus; PROCEDURE PrependInt(VAR sb : StringBuilder; n : INTEGER);VAR i : CARDINAL;BEGIN    i := sb.ptr;    INC(sb.ptr);    sb.buf[sb.ptr] := 0C;    WHILE i > 0 DO        sb.buf[i] := sb.buf[i-1];        DEC(i)    END;           sb.buf[0] := ToChar(n)END PrependInt; PROCEDURE Reverse(VAR str : String);VAR    i,j : CARDINAL;    c : CHAR;BEGIN    IF str[0] = 0C THEN RETURN END;    i := 0;    WHILE str[i] # 0C DO INC(i) END;    DEC(i);    j := 0;    WHILE i > j DO        c := str[i];        str[i] := str[j];        str[j] := c;         DEC(i);        INC(j)    ENDEND Reverse; PROCEDURE TrimStart(VAR str : String; c : CHAR);VAR i : CARDINAL;BEGIN                WHILE str[0] = c DO        i := 0;        WHILE str[i] # 0C DO            str[i] := str[i+1];            INC(i)        END    ENDEND TrimStart; PROCEDURE WriteInteger(n : INTEGER);VAR buf : ARRAY[0..15] OF CHAR;BEGIN    FormatString("%i", buf, n);    WriteString(buf)END WriteInteger; (* Imaginary *)TYPE    Complex = RECORD        real,imag : REAL;     END;    QuaterImaginary = RECORD        b2i : String;    END; PROCEDURE ComplexMul(lhs,rhs : Complex) : Complex;BEGIN             RETURN Complex{        rhs.real * lhs.real - rhs.imag * lhs.imag,        rhs.real * lhs.imag + rhs.imag * lhs.real    }                            END ComplexMul; PROCEDURE ComplexMulR(lhs : Complex; rhs : REAL) : Complex;BEGIN             RETURN Complex{lhs.real * rhs, lhs.imag * rhs}                            END ComplexMulR; PROCEDURE ComplexInv(c : Complex) : Complex;VAR denom : REAL;BEGIN    denom := c.real * c.real + c.imag * c.imag;    RETURN Complex{c.real / denom, -c.imag / denom}END ComplexInv; PROCEDURE ComplexDiv(lhs,rhs : Complex) : Complex;BEGIN                                         RETURN ComplexMul(lhs, ComplexInv(rhs))END ComplexDiv; PROCEDURE ComplexNeg(c : Complex) : Complex;BEGIN    RETURN Complex{-c.real, -c.imag}END ComplexNeg; PROCEDURE ComplexSum(lhs,rhs : Complex) : Complex;BEGIN                                         RETURN Complex{lhs.real + rhs.real, lhs.imag + rhs.imag}END ComplexSum; PROCEDURE WriteComplex(c : Complex);VAR buf : ARRAY[0..15] OF CHAR;BEGIN                        IF c.imag = 0.0 THEN              WriteInteger(INT(c.real))    ELSIF c.real = 0.0 THEN        WriteInteger(INT(c.imag));        WriteString("i")    ELSIF c.imag > 0.0 THEN        WriteInteger(INT(c.real));        WriteString(" + ");        WriteInteger(INT(c.imag));        WriteString("i")    ELSE        WriteInteger(INT(c.real));        WriteString(" - ");        WriteInteger(INT(-c.imag));        WriteString("i")    ENDEND WriteComplex; PROCEDURE ToQuaterImaginary(c : Complex) : QuaterImaginary;VAR    re,im,fi,rem,index : INTEGER;    f : REAL;    t : Complex;    sb : StringBuilder;BEGIN    IF (c.real = 0.0) AND (c.imag = 0.0) THEN RETURN QuaterImaginary{"0"} END;    re := INT(c.real);    im := INT(c.imag);    fi := -1;    sb := StringBuilder{"", 0};        WHILE re # 0 DO        rem := Modulus(re, -4);        re := re / (-4);        IF rem < 0 THEN            rem := 4 + rem;            INC(re)        END;        AppendInt(sb, rem);        AppendInt(sb, 0)    END;    IF im # 0 THEN        t := ComplexDiv(Complex{0.0, c.imag}, Complex{0.0, 2.0});        f := t.real;        im := INT(Ceil(f));        f := -4.0 * (f - FLOAT(im));        index := 1;        WHILE im # 0 DO            rem := Modulus(im, -4);            im := im / (-4);            IF rem < 0 THEN                rem := 4 + rem;                INC(im)            END;            IF index < INT(sb.ptr) THEN                sb.buf[index] := ToChar(rem)            ELSE                AppendInt(sb, 0);                AppendInt(sb, rem)            END;            index := index + 2;        END;        fi := INT(f)    END;    Reverse(sb.buf);    IF fi # -1 THEN        AppendChar(sb, '.');        AppendInt(sb, fi)    END;    TrimStart(sb.buf, '0');    IF sb.buf[0] = '.' THEN        PrependInt(sb, 0)    END;     RETURN QuaterImaginary{sb.buf}END ToQuaterImaginary; PROCEDURE ToComplex(qi : QuaterImaginary) : Complex;VAR    j,pointPos,posLen,b2iLen : INTEGER;    k : REAL;    sum,prod : Complex;BEGIN           pointPos := 0;    WHILE (qi.b2i[pointPos] # 0C) AND (qi.b2i[pointPos] # '.') DO        INC(pointPos)    END;                IF qi.b2i[pointPos] # '.' THEN        pointPos := -1;        posLen := 0;        WHILE qi.b2i[posLen] # 0C DO            INC(posLen)        END    ELSE        posLen := pointPos    END;     sum := Complex{0.0, 0.0};    prod := Complex{1.0, 0.0};     FOR j:=0 TO posLen - 1 DO        k := FLOAT(ORD(qi.b2i[posLen - 1 - j]) - ORD('0'));        IF k > 0.0 THEN            sum := ComplexSum(sum, ComplexMulR(prod, k))        END;        prod := ComplexMul(prod, Complex{0.0, 2.0})    END;     IF pointPos # -1 THEN        prod := ComplexInv(Complex{0.0, 2.0});        b2iLen := 0;        WHILE qi.b2i[b2iLen] # 0C DO INC(b2iLen) END;        FOR j:=posLen + 1 TO b2iLen - 1 DO            k := FLOAT(ORD(qi.b2i[j]) - ORD('0'));            IF k > 0.0 THEN                sum := ComplexSum(sum, ComplexMulR(prod, k))            END;            prod := ComplexMul(prod, ComplexInv(Complex{0.0, 2.0}))        END    END;     RETURN sumEND ToComplex; (* Main *)VAR     c1,c2 : Complex;    qi : QuaterImaginary;    i : INTEGER;BEGIN    FOR i:=1 TO 16 DO        c1 := Complex{FLOAT(i), 0.0};        WriteComplex(c1);        WriteString(" -> ");        qi := ToQuaterImaginary(c1);        WriteString(qi.b2i);        WriteString(" -> ");        c2 := ToComplex(qi);        WriteComplex(c2);        WriteString("   ");         c1 := ComplexNeg(c1);        WriteComplex(c1);        WriteString(" -> ");        qi := ToQuaterImaginary(c1);        WriteString(qi.b2i);        WriteString(" -> ");        c2 := ToComplex(qi);        WriteComplex(c2);        WriteLn    END;    WriteLn;     FOR i:=1 TO 16 DO        c1 := Complex{0.0, FLOAT(i)};        WriteComplex(c1);        WriteString(" -> ");        qi := ToQuaterImaginary(c1);        WriteString(qi.b2i);        WriteString(" -> ");        c2 := ToComplex(qi);        WriteComplex(c2);        WriteString("   ");         c1 := ComplexNeg(c1);        WriteComplex(c1);        WriteString(" -> ");        qi := ToQuaterImaginary(c1);        WriteString(qi.b2i);        WriteString(" -> ");        c2 := ToComplex(qi);        WriteComplex(c2);        WriteLn    END;     ReadCharEND ImaginaryBase.`
Output:
```1 -> 1 -> 1   -1 -> 103 -> -1
2 -> 2 -> 2   -2 -> 102 -> -2
3 -> 3 -> 3   -3 -> 101 -> -3
4 -> 10300 -> 4   -4 -> 100 -> -4
5 -> 10301 -> 5   -5 -> 203 -> -5
6 -> 10302 -> 6   -6 -> 202 -> -6
7 -> 10303 -> 7   -7 -> 201 -> -7
8 -> 10200 -> 8   -8 -> 200 -> -8
9 -> 10201 -> 9   -9 -> 303 -> -9
10 -> 10202 -> 10   -10 -> 302 -> -10
11 -> 10203 -> 11   -11 -> 301 -> -11
12 -> 10100 -> 12   -12 -> 300 -> -12
13 -> 10101 -> 13   -13 -> 1030003 -> -13
14 -> 10102 -> 14   -14 -> 1030002 -> -14
15 -> 10103 -> 15   -15 -> 1030001 -> -15
16 -> 10000 -> 16   -16 -> 1030000 -> -16

1i -> 10.2 -> 1i   -1i -> 0.2 -> -1i
2i -> 10.0 -> 2i   -2i -> 1030.0 -> -2i
3i -> 20.2 -> 3i   -3i -> 1030.2 -> -3i
4i -> 20.0 -> 4i   -4i -> 1020.0 -> -4i
5i -> 30.2 -> 5i   -5i -> 1020.2 -> -5i
6i -> 30.0 -> 6i   -6i -> 1010.0 -> -6i
7i -> 103000.2 -> 7i   -7i -> 1010.2 -> -7i
8i -> 103000.0 -> 8i   -8i -> 1000.0 -> -8i
9i -> 103010.2 -> 9i   -9i -> 1000.2 -> -9i
10i -> 103010.0 -> 10i   -10i -> 2030.0 -> -10i
11i -> 103020.2 -> 11i   -11i -> 2030.2 -> -11i
12i -> 103020.0 -> 12i   -12i -> 2020.0 -> -12i
13i -> 103030.2 -> 13i   -13i -> 2020.2 -> -13i
14i -> 103030.0 -> 14i   -14i -> 2010.0 -> -14i
15i -> 102000.2 -> 15i   -15i -> 2010.2 -> -15i
16i -> 102000.0 -> 16i   -16i -> 2000.0 -> -16i```

Nim

Translation of: Kotlin

This is a fairly faithful translation of the Kotlin program except that we had not to define a Complex type as Nim provides the module “complex” in its standard library. We had only to define a function “toString” for the “Complex[float]” type, function to use in place of “\$” in order to get a more pleasant output.

`import algorithm, complex, math, strformat, strutils const  TwoI = complex(0.0, 2.0)  InvTwoI = inv(TwoI) type QuaterImaginery = object  b2i: string # Conversions between digit character and digit value.template digitChar(n: range[0..9]): range['0'..'9'] = chr(n + ord('0'))template digitValue(c: range['0'..'9']): range[0..9] = ord(c) - ord('0')  ##################################################################################################### Quater imaginary functions. func initQuaterImaginary(s: string): QuaterImaginery =  ## Create a Quater imaginary number.  if s.len == 0 or not s.allCharsInSet({'0'..'3', '.'}) or s.count('.') > 1:    raise newException(ValueError, "invalid base 2i number.")  result = QuaterImaginery(b2i: s) #--------------------------------------------------------------------------------------------------- func toComplex(q: QuaterImaginery): Complex[float] =  ## Convert a Quater imaginary number to a complex.   let pointPos = q.b2i.find('.')  let posLen = if pointPos != -1: pointPos else: q.b2i.len  var prod = complex(1.0)   for j in 0..<posLen:    let k = float(q.b2i[posLen - 1 - j].digitValue)    if k > 0: result += prod * k    prod *= TwoI   if pointPos != -1:    prod = InvTwoI    for j in (posLen + 1)..q.b2i.high:      let k = float(q.b2i[j].digitValue)      if k > 0: result += prod * k      prod *= InvTwoI #--------------------------------------------------------------------------------------------------- func `\$`(q: QuaterImaginery): string =  ## Convert a Quater imaginary number to a string.  q.b2i  ##################################################################################################### Supplementary functions for complex numbers. func toQuaterImaginary(c: Complex): QuaterImaginery =  ## Convert a complex number to a Quater imaginary number.   if c.re == 0 and c.im == 0: return initQuaterImaginary("0")   var re = c.re.toInt  var im = c.im.toInt  var fi = -1   while re != 0:    var rem = re mod -4    re = re div -4    if rem < 0:      inc rem, 4      inc re    result.b2i.add rem.digitChar    result.b2i.add '0'   if im != 0:    var f = (complex(0.0, c.im) / TwoI).re    im = f.ceil.toInt    f = -4 * (f - im.toFloat)    var index = 1    while im != 0:      var rem = im mod -4      im = im div -4      if rem < 0:        inc rem, 4        inc im      if index < result.b2i.len:        result.b2i[index] = rem.digitChar      else:        result.b2i.add '0'        result.b2i.add rem.digitChar      inc index, 2    fi = f.toInt   result.b2i.reverse()  if fi != -1: result.b2i.add "." & \$fi  result.b2i = result.b2i.strip(leading = true, trailing = false, {'0'})  if result.b2i.startsWith('.'): result.b2i = '0' & result.b2i #--------------------------------------------------------------------------------------------------- func toString(c: Complex[float]): string =  ## Convert a complex number to a string.  ## This function is used in place of `\$`.   let real = if c.re.classify == fcNegZero: 0.0 else: c.re  let imag = if c.im.classify == fcNegZero: 0.0 else: c.im  result = if imag >= 0: fmt"{real} + {imag}i" else: fmt"{real} - {-imag}i"  result = result.replace(".0 ", " ").replace(".0i", "i").replace(" + 0i", "")  if result.startsWith("0 + "): result = result[4..^1]  if result.startsWith("0 - "): result = '-' & result[4..^1]  #——————————————————————————————————————————————————————————————————————————————————————————————————— when isMainModule:   for i in 1..16:    var c1 = complex(i.toFloat)    var qi = c1.toQuaterImaginary    var c2 = qi.toComplex    stdout.write fmt"{c1.toString:>4s} → {qi:>8s} → {c2.toString:>4s}     "    c1 = -c1    qi = c1.toQuaterImaginary    c2 = qi.toComplex    echo fmt"{c1.toString:>4s} → {qi:>8s} → {c2.toString:>4s}"   echo ""   for i in 1..16:    var c1 = complex(0.0, i.toFloat)    var qi = c1.toQuaterImaginary    var c2 = qi.toComplex    stdout.write fmt"{c1.toString:>4s} → {qi:>8s} → {c2.toString:>4s}     "    c1 = -c1    qi = c1.toQuaterImaginary    c2 = qi.toComplex    echo fmt"{c1.toString:>4s} → {qi:>8s} → {c2.toString:>4s}"`
Output:
```   1 →        1 →    1       -1 →      103 →   -1
2 →        2 →    2       -2 →      102 →   -2
3 →        3 →    3       -3 →      101 →   -3
4 →    10300 →    4       -4 →      100 →   -4
5 →    10301 →    5       -5 →      203 →   -5
6 →    10302 →    6       -6 →      202 →   -6
7 →    10303 →    7       -7 →      201 →   -7
8 →    10200 →    8       -8 →      200 →   -8
9 →    10201 →    9       -9 →      303 →   -9
10 →    10202 →   10      -10 →      302 →  -10
11 →    10203 →   11      -11 →      301 →  -11
12 →    10100 →   12      -12 →      300 →  -12
13 →    10101 →   13      -13 →  1030003 →  -13
14 →    10102 →   14      -14 →  1030002 →  -14
15 →    10103 →   15      -15 →  1030001 →  -15
16 →    10000 →   16      -16 →  1030000 →  -16

1i →     10.2 →   1i      -1i →      0.2 →  -1i
2i →     10.0 →   2i      -2i →   1030.0 →  -2i
3i →     20.2 →   3i      -3i →   1030.2 →  -3i
4i →     20.0 →   4i      -4i →   1020.0 →  -4i
5i →     30.2 →   5i      -5i →   1020.2 →  -5i
6i →     30.0 →   6i      -6i →   1010.0 →  -6i
7i → 103000.2 →   7i      -7i →   1010.2 →  -7i
8i → 103000.0 →   8i      -8i →   1000.0 →  -8i
9i → 103010.2 →   9i      -9i →   1000.2 →  -9i
10i → 103010.0 →  10i     -10i →   2030.0 → -10i
11i → 103020.2 →  11i     -11i →   2030.2 → -11i
12i → 103020.0 →  12i     -12i →   2020.0 → -12i
13i → 103030.2 →  13i     -13i →   2020.2 → -13i
14i → 103030.0 →  14i     -14i →   2010.0 → -14i
15i → 102000.2 →  15i     -15i →   2010.2 → -15i
16i → 102000.0 →  16i     -16i →   2000.0 → -16i```

Perl

Translation of: Raku
Library: ntheory
`use strict;use warnings;use feature 'say'; use Math::Complex;use List::AllUtils qw(sum mesh);use ntheory qw<todigitstring fromdigits>; sub zip {    my(\$a,\$b) = @_;    my(\$la, \$lb) = (length \$a, length \$b);    my \$l = '0' x abs \$la - \$lb;    \$a .= \$l if \$la < \$lb;    \$b .= \$l if \$lb < \$la;    (join('', mesh(@{[split('',\$a),]}, @{[split('',\$b),]})) =~ s/0+\$//r) or 0;} sub base_i {    my(\$num,\$radix,\$precision) = @_;    die unless \$radix > -37 and \$radix < -1;    return '0' unless \$num;    my \$value  = \$num;    my \$result = '';    my \$place  = 0;    my \$upper_bound = 1 / (-\$radix + 1);    my \$lower_bound = \$radix * \$upper_bound;     \$value = \$num / \$radix ** ++\$place until \$lower_bound <= \$value and \$value < \$upper_bound;     while ((\$value or \$place > 0) and \$place > \$precision) {        my \$digit = int \$radix * \$value - \$lower_bound;        \$value    =  \$radix * \$value - \$digit;        \$result  .= '.' unless \$place or not index(\$result, '.');        \$result  .= \$digit == -\$radix ? todigitstring(\$digit-1, -\$radix) . '0' : (todigitstring(\$digit, -\$radix) or '0');        \$place--;    }    \$result} sub base_c {    my(\$num, \$radix, \$precision) = @_;    die "Base \$radix out of range" unless        (-6 <= \$radix->Im or \$radix->Im <= -2) or (2 <= \$radix->Im or \$radix->Im <= 6);    my (\$re,\$im);    defined \$num->Im ? (\$re, \$im) = (\$num->Re, \$num->Im) : \$re = \$num;    my (\$re_wh, \$re_fr) = split /\./, base_i(  \$re,               -1 * int(\$radix->Im**2), \$precision);    my (\$im_wh, \$im_fr) = split /\./, base_i( (\$im/(\$radix->Im)), -1 * int(\$radix->Im**2), \$precision);    \$_ //= '' for \$re_fr, \$im_fr;     my \$whole = reverse zip scalar reverse(\$re_wh), scalar reverse(\$im_wh);    my \$fraction = zip \$im_fr, \$re_fr;    \$fraction eq 0 ? "\$whole" : "\$whole.\$fraction"} sub parse_base {    my(\$str, \$radix) = @_;    return -1 * parse_base( substr(\$str,1), \$radix) if substr(\$str,0,1) eq '-';    my(\$whole, \$frac) = split /\./, \$str;    my \$fraction = 0;    my \$k = 0;    \$fraction = sum map { (fromdigits(\$_, int \$radix->Im**2) || 0) * \$radix ** -(\$k++ +1) } split '', \$frac        if \$frac;    \$k = 0;    \$fraction + sum map { (fromdigits(\$_, int \$radix->Im**2) || 0) * \$radix ** \$k++  } reverse split '', \$whole;} for (    [  0*i,  2*i], [1+0*i,  2*i], [5+0*i,      2*i], [ -13+0*i, 2*i],    [  9*i,  2*i], [ -3*i,  2*i], [7.75-7.5*i, 2*i], [0.25+0*i, 2*i],    [5+5*i,  2*i], [5+5*i,  3*i], [5+5*i,  4*i], [5+5*i,  5*i], [5+5*i,  6*i],    [5+5*i, -2*i], [5+5*i, -3*i], [5+5*i, -4*i], [5+5*i, -5*i], [5+5*i, -6*i]) {    my(\$v,\$r) = @\$_;    my \$ibase = base_c(\$v, \$r, -6);    my \$rt = cplx parse_base(\$ibase, \$r);    \$rt->display_format('format' => '%.2f');    printf "base(%3s): %10s  => %9s  => %13s\n", \$r, \$v, \$ibase, \$rt;} say '';say 'base( 6i): 31432.6219135802-2898.5266203704*i => ' .         base_c(31432.6219135802-2898.5266203704*i, 0+6*i, -3);`
Output:
```base( 2i):          0  =>         0  =>             0
base( 2i):          1  =>         1  =>          1.00
base( 2i):          5  =>     10301  =>    5.00-0.00i
base( 2i):        -13  =>   1030003  =>  -13.00+0.00i
base( 2i):         9i  =>  103010.2  =>    0.00+9.00i
base( 2i):        -3i  =>    1030.2  =>   -0.00-3.00i
base( 2i):  7.75-7.5i  =>  11210.31  =>    7.75-7.50i
base( 2i):       0.25  =>      1.03  =>    0.25-0.00i
base( 2i):       5+5i  =>   10331.2  =>    5.00+5.00i
base( 3i):       5+5i  =>      25.3  =>    5.00+5.00i
base( 4i):       5+5i  =>      25.c  =>    5.00+5.00i
base( 5i):       5+5i  =>        15  =>    5.00+5.00i
base( 6i):       5+5i  =>      15.6  =>    5.00+5.00i
base(-2i):       5+5i  =>   11321.2  =>    5.00+5.00i
base(-3i):       5+5i  =>    1085.6  =>    5.00+5.00i
base(-4i):       5+5i  =>    10f5.4  =>    5.00+5.00i
base(-5i):       5+5i  =>      10o5  =>    5.00+5.00i
base(-6i):       5+5i  =>       5.u  =>    5.00+5.00i

base( 6i): 31432.6219135802-2898.5266203704*i => perl5.4ever```

Phix

Translation of: Sidef
`include complex.e function base2(atom num, integer radix, precision = -8)    if radix<-36 or radix>-2 then throw("radix out of range (-2..-36)") end if    sequence result    if num=0 then        result = {"0",""}    else        integer place = 0        result = ""        atom v = num        atom upper_bound = 1/(1-radix),             lower_bound = radix*upper_bound        while not(lower_bound <= v) or not(v < upper_bound) do            place += 1            v = num/power(radix,place)        end while         while (v or place > 0) and (place > precision) do            integer digit = floor(radix*v - lower_bound)            v = (radix*v - digit)            if place=0 and not find('.',result) then result &= '.' end if            result &= digit+iff(digit>9?'a'-10:'0')            place -= 1        end while        integer dot = find('.',result)        if dot then            result = trim_tail(result,'0')            result = {result[1..dot-1],result[dot+1..\$]}        else            result = {result,""}        end if    end if    return resultend function function zip(string a, string b)    integer ld = length(a)-length(b)    if ld!=0 then        if ld>0 then            b &= repeat('0',ld)        else            a &= repeat('0',abs(ld))        end if    end if    string res = ""    for i=1 to length(a) do        res &= a[i]&b[i]    end for    res = trim_tail(res,'0')    if res="" then res = "0" end if    return resend function function base(complexn num, integer radix, precision = -8)     integer absrad = abs(radix),            radix2 = -power(radix,2)    if absrad<2 or absrad>6 then throw("base radix out of range") end if     atom {re, im}         = {complex_real(num), complex_imag(num)}    string {re_wh, re_fr} = base2(re,       radix2, precision),           {im_wh, im_fr} = base2(im/radix, radix2, precision)     string whole = reverse(zip(reverse(re_wh), reverse(im_wh))),           fraction = zip(im_fr, re_fr)    if fraction!="0" then whole &= '.'&fraction end if    return wholeend function function parse_base(string str, integer radix)     complexn fraction = 0     integer dot = find('.',str)    if dot then        string fr = str[dot+1..\$]        for i=1 to length(fr) do            integer c = fr[i]            c -= iff(c>='a'?'a'-10:'0')            fraction = complex_add(fraction,complex_mul(c,complex_power({0,radix},-i)))        end for        str = str[1..dot-1]    end if     str = reverse(str)    for i=1 to length(str) do        integer c = str[i]        c -= iff(c>='a'?'a'-10:'0')        fraction = complex_add(fraction,complex_mul(c,complex_power({0,radix},(i-1))))    end for     return fractionend function constant tests = {{0,2},{1,2},{5,2},{-13,2},{{0,9},2},{{0,-3},2},{{7.75,-7.5}, 2},{.25, 2}, -- base 2i tests                  {{5,5}, 2},{{5,5}, 3},{{5,5}, 4},{{5,5}, 5},{{5,5}, 6}, -- same value, positive imaginary bases                  {{5,5},-2},{{5,5},-3},{{5,5},-4},{{5,5},-5},{{5,5},-6}, -- same value, negative imaginary bases                  {{227.65625,10.859375},4}, -- larger test value                  {{-579.8225308641975744,-5296.406378600824},6}}   -- phix.rules -- matches output of Sidef and Raku:for t=1 to length(tests) do    {complexn v, integer r} = tests[t]    string ibase = base(v,r),           strv = complex_sprint(v),           strb = complex_sprint(parse_base(ibase, r))    printf(1,"base(%20s, %2di) = %-10s : parse_base(%12s, %2di) = %s\n",                  {strv,  r,     ibase,    '"'&ibase&'"', r,     strb})end for -- matches output of Kotlin, Java, Go, D, and C#:for ri=1 to 2 do    -- real then imag    for i=1 to 16 do        complexn c = iff(ri=1?i:{0,i}),                nc = complex_neg(c)        string sc = complex_sprint(c),              snc = complex_sprint(nc),               ib = base(c,2),              inb = base(nc,2),               rc = complex_sprint(parse_base(ib,2)),              rnc = complex_sprint(parse_base(inb,2))        printf(1,"%4s -> %8s -> %4s     %4s -> %8s -> %4s\n",                 {sc,    ib,    rc,     snc,   inb,   rnc })    end for    puts(1,"\n")end for`
Output:

Matches the output of Sidef and Raku, except for the final line:

```base(   -579.823-5296.41i,  6i) = phix.rules : parse_base("phix.rules",  6i) = -579.823-5296.41i
```

Also matches the output of Kotlin, Java, Go, D, and C#, except the even entries in the second half, eg:

```  2i ->       10 ->   2i      -2i ->     1030 ->  -2i
```

instead of

```  2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
```

ie the unnecessary trailing ".0" are trimmed. (see talk page)

Python

Translation of: C++
`import mathimport re def inv(c):    denom = c.real * c.real + c.imag * c.imag    return complex(c.real / denom, -c.imag / denom) class QuaterImaginary:    twoI = complex(0, 2)    invTwoI = inv(twoI)     def __init__(self, str):        if not re.match("^[0123.]+\$", str) or str.count('.') > 1:            raise Exception('Invalid base 2i number')        self.b2i = str     def toComplex(self):        pointPos = self.b2i.find('.')        posLen = len(self.b2i) if (pointPos < 0) else pointPos        sum = complex(0, 0)        prod = complex(1, 0)        for j in xrange(0, posLen):            k = int(self.b2i[posLen - 1 - j])            if k > 0:                sum += prod * k            prod *= QuaterImaginary.twoI        if pointPos != -1:            prod = QuaterImaginary.invTwoI            for j in xrange(posLen + 1, len(self.b2i)):                k = int(self.b2i[j])                if k > 0:                    sum += prod * k                prod *= QuaterImaginary.invTwoI        return sum     def __str__(self):        return str(self.b2i) def toQuaterImaginary(c):    if c.real == 0.0 and c.imag == 0.0:        return QuaterImaginary("0")     re = int(c.real)    im = int(c.imag)    fi = -1    ss = ""    while re != 0:        re, rem = divmod(re, -4)        if rem < 0:            rem += 4            re += 1        ss += str(rem) + '0'    if im != 0:        f = c.imag / 2        im = int(math.ceil(f))        f = -4 * (f - im)        index = 1        while im != 0:            im, rem = divmod(im, -4)            if rem < 0:                rem += 4                im += 1            if index < len(ss):                ss[index] = str(rem)            else:                ss += '0' + str(rem)            index = index + 2        fi = int(f)    ss = ss[::-1]    if fi != -1:        ss += '.' + str(fi)    ss = ss.lstrip('0')    if ss[0] == '.':        ss = '0' + ss    return QuaterImaginary(ss) for i in xrange(1,17):    c1 = complex(i, 0)    qi = toQuaterImaginary(c1)    c2 = qi.toComplex()    print "{0:8} -> {1:>8} -> {2:8}     ".format(c1, qi, c2),     c1 = -c1    qi = toQuaterImaginary(c1)    c2 = qi.toComplex()    print "{0:8} -> {1:>8} -> {2:8}".format(c1, qi, c2)print for i in xrange(1,17):    c1 = complex(0, i)    qi = toQuaterImaginary(c1)    c2 = qi.toComplex()    print "{0:8} -> {1:>8} -> {2:8}     ".format(c1, qi, c2),     c1 = -c1    qi = toQuaterImaginary(c1)    c2 = qi.toComplex()    print "{0:8} -> {1:>8} -> {2:8}".format(c1, qi, c2) print "done" `
Output:
```  (1+0j) ->        1 ->   (1+0j)       (-1-0j) ->      103 ->  (-1+0j)
(2+0j) ->        2 ->   (2+0j)       (-2-0j) ->      102 ->  (-2+0j)
(3+0j) ->        3 ->   (3+0j)       (-3-0j) ->      101 ->  (-3+0j)
(4+0j) ->    10300 ->   (4+0j)       (-4-0j) ->      100 ->  (-4+0j)
(5+0j) ->    10301 ->   (5+0j)       (-5-0j) ->      203 ->  (-5+0j)
(6+0j) ->    10302 ->   (6+0j)       (-6-0j) ->      202 ->  (-6+0j)
(7+0j) ->    10303 ->   (7+0j)       (-7-0j) ->      201 ->  (-7+0j)
(8+0j) ->    10200 ->   (8+0j)       (-8-0j) ->      200 ->  (-8+0j)
(9+0j) ->    10201 ->   (9+0j)       (-9-0j) ->      303 ->  (-9+0j)
(10+0j) ->    10202 ->  (10+0j)      (-10-0j) ->      302 -> (-10+0j)
(11+0j) ->    10203 ->  (11+0j)      (-11-0j) ->      301 -> (-11+0j)
(12+0j) ->    10100 ->  (12+0j)      (-12-0j) ->      300 -> (-12+0j)
(13+0j) ->    10101 ->  (13+0j)      (-13-0j) ->  1030003 -> (-13+0j)
(14+0j) ->    10102 ->  (14+0j)      (-14-0j) ->  1030002 -> (-14+0j)
(15+0j) ->    10103 ->  (15+0j)      (-15-0j) ->  1030001 -> (-15+0j)
(16+0j) ->    10000 ->  (16+0j)      (-16-0j) ->  1030000 -> (-16+0j)

1j ->     10.2 ->       1j       (-0-1j) ->      0.2 ->      -1j
2j ->     10.0 ->       2j       (-0-2j) ->   1030.0 ->      -2j
3j ->     20.2 ->       3j       (-0-3j) ->   1030.2 ->      -3j
4j ->     20.0 ->       4j       (-0-4j) ->   1020.0 ->      -4j
5j ->     30.2 ->       5j       (-0-5j) ->   1020.2 ->      -5j
6j ->     30.0 ->       6j       (-0-6j) ->   1010.0 ->      -6j
7j -> 103000.2 ->       7j       (-0-7j) ->   1010.2 ->      -7j
8j -> 103000.0 ->       8j       (-0-8j) ->   1000.0 ->      -8j
9j -> 103010.2 ->       9j       (-0-9j) ->   1000.2 ->      -9j
10j -> 103010.0 ->      10j      (-0-10j) ->   2030.0 ->     -10j
11j -> 103020.2 ->      11j      (-0-11j) ->   2030.2 ->     -11j
12j -> 103020.0 ->      12j      (-0-12j) ->   2020.0 ->     -12j
13j -> 103030.2 ->      13j      (-0-13j) ->   2020.2 ->     -13j
14j -> 103030.0 ->      14j      (-0-14j) ->   2010.0 ->     -14j
15j -> 102000.2 ->      15j      (-0-15j) ->   2010.2 ->     -15j
16j -> 102000.0 ->      16j      (-0-16j) ->   2000.0 ->     -16j
done```

Raku

(formerly Perl 6)

Explicit

Works with: Rakudo version 2017.01

These are generalized imaginary-base conversion routines. They only work for imaginary bases, not complex. (Any real portion of the radix must be zero.) Theoretically they could be made to work for any imaginary base; in practice, they are limited to integer bases from -6i to -2i and 2i to 6i. Bases -1i and 1i exist but require special handling and are not supported. Bases larger than 6i (or -6i) require digits outside of base 36 to express them, so aren't as standardized, are implementation dependent and are not supported. Note that imaginary number coefficients are stored as floating point numbers in Raku so some rounding error may creep in during calculations. The precision these conversion routines use is configurable; we are using 6 decimal, um... radicimal(?) places of precision here.

Implements minimum, extra kudos and stretch goals.

`multi sub base ( Real \$num, Int \$radix where -37 < * < -1, :\$precision = -15 ) {    return '0' unless \$num;    my \$value  = \$num;    my \$result = '';    my \$place  = 0;    my \$upper-bound = 1 / (-\$radix + 1);    my \$lower-bound = \$radix * \$upper-bound;     \$value = \$num / \$radix ** ++\$place until \$lower-bound <= \$value < \$upper-bound;     while (\$value or \$place > 0) and \$place > \$precision {        my \$digit = (\$radix * \$value - \$lower-bound).Int;        \$value    =  \$radix * \$value - \$digit;        \$result ~= '.' unless \$place or \$result.contains: '.';        \$result ~= \$digit == -\$radix ?? (\$digit-1).base(-\$radix)~'0' !! \$digit.base(-\$radix);        \$place--    }    \$result} multi sub base (Numeric \$num, Complex \$radix where *.re == 0, :\$precision = -8 ) {    die "Base \$radix out of range" unless -6 <= \$radix.im <= -2 or 2 <= \$radix.im <= 6;    my (\$re, \$im) = \$num.Complex.reals;    my (\$re-wh, \$re-fr) =             \$re.&base( -\$radix.im².Int, :precision(\$precision) ).split: '.';    my (\$im-wh, \$im-fr) = (\$im/\$radix.im).&base( -\$radix.im².Int, :precision(\$precision) ).split: '.';    \$_ //= '' for \$re-fr, \$im-fr;     sub zip (Str \$a, Str \$b) {        my \$l = '0' x (\$a.chars - \$b.chars).abs;        ([~] flat (\$a~\$l).comb Z flat (\$b~\$l).comb).subst(/ '0'+ \$ /, '') || '0'    }     my \$whole = flip zip \$re-wh.flip, \$im-wh.flip;    my \$fraction = zip \$im-fr, \$re-fr;    \$fraction eq 0 ?? "\$whole" !! "\$whole.\$fraction"} multi sub parse-base (Str \$str, Complex \$radix where *.re == 0) {    return -1 * \$str.substr(1).&parse-base(\$radix) if \$str.substr(0,1) eq '-';    my (\$whole, \$frac) = \$str.split: '.';    my \$fraction = 0;    \$fraction = [+] \$frac.comb.kv.map: { \$^v.parse-base(\$radix.im².Int) * \$radix ** -(\$^k+1) } if \$frac;    \$fraction + [+] \$whole.flip.comb.kv.map: { \$^v.parse-base(\$radix.im².Int) * \$radix ** \$^k }} # TESTINGfor 0, 2i, 1, 2i, 5, 2i, -13, 2i, 9i, 2i, -3i, 2i, 7.75-7.5i, 2i, .25, 2i, # base 2i tests    5+5i,  2i, 5+5i,  3i, 5+5i,  4i, 5+5i,  5i, 5+5i,  6i, # same value, positive imaginary bases    5+5i, -2i, 5+5i, -3i, 5+5i, -4i, 5+5i, -5i, 5+5i, -6i, # same value, negative imaginary bases    227.65625+10.859375i, 4i, # larger test value    31433.3487654321-2902.4480452675i, 6i # heh  -> \$v, \$r {my \$ibase = \$v.&base(\$r, :precision(-6));printf "%33s.&base\(%2si\) = %-11s : %13s.&parse-base\(%2si\) = %s\n",  \$v, \$r.im, \$ibase, "'\$ibase'", \$r.im, \$ibase.&parse-base(\$r).round(1e-10).narrow;}`
Output:
```                                0.&base( 2i) = 0           :           '0'.&parse-base( 2i) = 0
1.&base( 2i) = 1           :           '1'.&parse-base( 2i) = 1
5.&base( 2i) = 10301       :       '10301'.&parse-base( 2i) = 5
-13.&base( 2i) = 1030003     :     '1030003'.&parse-base( 2i) = -13
0+9i.&base( 2i) = 103010.2    :    '103010.2'.&parse-base( 2i) = 0+9i
-0-3i.&base( 2i) = 1030.2      :      '1030.2'.&parse-base( 2i) = 0-3i
7.75-7.5i.&base( 2i) = 11210.31    :    '11210.31'.&parse-base( 2i) = 7.75-7.5i
0.25.&base( 2i) = 1.03        :        '1.03'.&parse-base( 2i) = 0.25
5+5i.&base( 2i) = 10331.2     :     '10331.2'.&parse-base( 2i) = 5+5i
5+5i.&base( 3i) = 25.3        :        '25.3'.&parse-base( 3i) = 5+5i
5+5i.&base( 4i) = 25.C        :        '25.C'.&parse-base( 4i) = 5+5i
5+5i.&base( 5i) = 15          :          '15'.&parse-base( 5i) = 5+5i
5+5i.&base( 6i) = 15.6        :        '15.6'.&parse-base( 6i) = 5+5i
5+5i.&base(-2i) = 11321.2     :     '11321.2'.&parse-base(-2i) = 5+5i
5+5i.&base(-3i) = 1085.6      :      '1085.6'.&parse-base(-3i) = 5+5i
5+5i.&base(-4i) = 10F5.4      :      '10F5.4'.&parse-base(-4i) = 5+5i
5+5i.&base(-5i) = 10O5        :        '10O5'.&parse-base(-5i) = 5+5i
5+5i.&base(-6i) = 5.U         :         '5.U'.&parse-base(-6i) = 5+5i
227.65625+10.859375i.&base( 4i) = 10234.5678  :  '10234.5678'.&parse-base( 4i) = 227.65625+10.859375i
31433.3487654321-2902.4480452675i.&base( 6i) = PERL6.ROCKS : 'PERL6.ROCKS'.&parse-base( 6i) = 31433.3487654321-2902.4480452675i```

Module

Works with: Rakudo version 2020.02

Using the module Base::Any from the Raku ecosystem.

Does everything the explicit version does but also handles a much larger range of imaginary bases.

Doing pretty much the same tests as the explicit version.

`use Base::Any; # TESTINGfor 0, 2i, 1, 2i, 5, 2i, -13, 2i, 9i, 2i, -3i, 2i, 7.75-7.5i, 2i, .25, 2i, # base 2i tests    5+5i,  2i, 5+5i,  3i, 5+5i,  4i, 5+5i,  5i, 5+5i,  6i, # same value, positive imaginary bases    5+5i, -2i, 5+5i, -3i, 5+5i, -4i, 5+5i, -5i, 5+5i, -6i, # same value, negative imaginary bases    227.65625+10.859375i, 4i, # larger test value    31433.3487654321-2902.4480452675i, 6i, # heh    -3544.29+26541.468i, -10i  -> \$v, \$r {    my \$ibase = \$v.&to-base(\$r, :precision(-6));    printf "%33s.&to-base\(%3si\) = %-11s : %13s.&from-base\(%3si\) = %s\n",    \$v, \$r.im, \$ibase, "'\$ibase'", \$r.im, \$ibase.&from-base(\$r).round(1e-10).narrow;}`
Output:
```                                0.&to-base(  2i) = 0           :           '0'.&from-base(  2i) = 0
1.&to-base(  2i) = 1           :           '1'.&from-base(  2i) = 1
5.&to-base(  2i) = 10301       :       '10301'.&from-base(  2i) = 5
-13.&to-base(  2i) = 1030003     :     '1030003'.&from-base(  2i) = -13
0+9i.&to-base(  2i) = 103010.2    :    '103010.2'.&from-base(  2i) = 0+9i
-0-3i.&to-base(  2i) = 1030.2      :      '1030.2'.&from-base(  2i) = 0-3i
7.75-7.5i.&to-base(  2i) = 11210.31    :    '11210.31'.&from-base(  2i) = 7.75-7.5i
0.25.&to-base(  2i) = 1.03        :        '1.03'.&from-base(  2i) = 0.25
5+5i.&to-base(  2i) = 10331.2     :     '10331.2'.&from-base(  2i) = 5+5i
5+5i.&to-base(  3i) = 25.3        :        '25.3'.&from-base(  3i) = 5+5i
5+5i.&to-base(  4i) = 25.C        :        '25.C'.&from-base(  4i) = 5+5i
5+5i.&to-base(  5i) = 15          :          '15'.&from-base(  5i) = 5+5i
5+5i.&to-base(  6i) = 15.6        :        '15.6'.&from-base(  6i) = 5+5i
5+5i.&to-base( -2i) = 11321.2     :     '11321.2'.&from-base( -2i) = 5+5i
5+5i.&to-base( -3i) = 1085.6      :      '1085.6'.&from-base( -3i) = 5+5i
5+5i.&to-base( -4i) = 10F5.4      :      '10F5.4'.&from-base( -4i) = 5+5i
5+5i.&to-base( -5i) = 10O5        :        '10O5'.&from-base( -5i) = 5+5i
5+5i.&to-base( -6i) = 5.U         :         '5.U'.&from-base( -6i) = 5+5i
227.65625+10.859375i.&to-base(  4i) = 10234.5678  :  '10234.5678'.&from-base(  4i) = 227.65625+10.859375i
31433.3487654321-2902.4480452675i.&to-base(  6i) = PERL6.ROCKS : 'PERL6.ROCKS'.&from-base(  6i) = 31433.3487654321-2902.4480452675i
-3544.29+26541.468i.&to-base(-10i) = Raku.FTW    :    'Raku.FTW'.&from-base(-10i) = -3544.29+26541.468i```

Sidef

Translation of: Raku
`func base (Number num, Number radix { _ ~~ (-36 .. -2) }, precision = -15) -> String {    num || return '0'     var place  = 0    var result = ''    var value  = num    var upper_bound = 1/(-radix + 1)    var lower_bound = radix*upper_bound     while (!(lower_bound <= value) || !(value < upper_bound)) {        value = num/(radix**++place)    }     while ((value || (place > 0)) && (place > precision)) {        var digit = (radix*value - lower_bound -> int)        value    =  (radix*value - digit)        result += '.' if (!place && !result.contains('.'))        result += ((digit == -radix) ? (digit-1 -> base(-radix) + '0') : digit.base(-radix))        place--    }     return result} func base (Number num, Number radix { .re == 0 }, precision = -8) -> String {     (radix.im.abs ~~ 2..6) || die "Base #{radix} out of range"     var (re, im)          = (num.re, num.im)    var (re_wh, re_fr='') = base(re,          -radix.im**2, precision).split('.')...    var (im_wh, im_fr='') = base(im/radix.im, -radix.im**2, precision).split('.')...     func zip (String a, String b) {        var l = ('0' * abs(a.len - b.len))        chars(a+l) ~Z chars(b+l) -> flat.join.sub(/0+\z/, '') || '0'    }     var whole = zip(re_wh.flip, im_wh.flip).flip    var fraction = zip(im_fr, re_fr)    fraction == '0' ? whole : "#{whole}.#{fraction}"} func parse_base (String str, Number radix { .re == 0 }) -> Number {     if (str.char(0) == '-') {        return (-1 * parse_base(str.substr(1), radix))    }     var (whole, frac='') = str.split('.')...     var fraction = frac.chars.map_kv {|k,v|        Number(v, radix.im**2) * radix**-(k+1)    }.sum     fraction += whole.flip.chars.map_kv {|k,v|        Number(v, radix.im**2) * radix**k    }.sum     return fraction} var tests = [0, 2i, 1, 2i, 5, 2i, -13, 2i, 9i, 2i, -3i, 2i, 7.75-7.5i, 2i, .25, 2i, # base 2i tests    5+5i,  2i, 5+5i,  3i, 5+5i,  4i, 5+5i,  5i, 5+5i,  6i, # same value, positive imaginary bases    5+5i, -2i, 5+5i, -3i, 5+5i, -4i, 5+5i, -5i, 5+5i, -6i, # same value, negative imaginary bases    227.65625+10.859375i, 4i] # larger test value tests.each_slice(2, {|v,r|    var ibase = base(v, r)    printf("base(%20s, %2si) = %-10s : parse_base(%12s, %2si) = %s\n",        v, r.im, ibase, "'#{ibase}'", r.im, parse_base(ibase, r).round(-8))})`
Output:
```base(                   0,  2i) = 0          : parse_base(         '0',  2i) = 0
base(                   1,  2i) = 1          : parse_base(         '1',  2i) = 1
base(                   5,  2i) = 10301      : parse_base(     '10301',  2i) = 5
base(                 -13,  2i) = 1030003    : parse_base(   '1030003',  2i) = -13
base(                  9i,  2i) = 103010.2   : parse_base(  '103010.2',  2i) = 9i
base(                 -3i,  2i) = 1030.2     : parse_base(    '1030.2',  2i) = -3i
base(           7.75-7.5i,  2i) = 11210.31   : parse_base(  '11210.31',  2i) = 7.75-7.5i
base(                0.25,  2i) = 1.03       : parse_base(      '1.03',  2i) = 0.25
base(                5+5i,  2i) = 10331.2    : parse_base(   '10331.2',  2i) = 5+5i
base(                5+5i,  3i) = 25.3       : parse_base(      '25.3',  3i) = 5+5i
base(                5+5i,  4i) = 25.c       : parse_base(      '25.c',  4i) = 5+5i
base(                5+5i,  5i) = 15         : parse_base(        '15',  5i) = 5+5i
base(                5+5i,  6i) = 15.6       : parse_base(      '15.6',  6i) = 5+5i
base(                5+5i, -2i) = 11321.2    : parse_base(   '11321.2', -2i) = 5+5i
base(                5+5i, -3i) = 1085.6     : parse_base(    '1085.6', -3i) = 5+5i
base(                5+5i, -4i) = 10f5.4     : parse_base(    '10f5.4', -4i) = 5+5i
base(                5+5i, -5i) = 10o5       : parse_base(      '10o5', -5i) = 5+5i
base(                5+5i, -6i) = 5.u        : parse_base(       '5.u', -6i) = 5+5i
base(227.65625+10.859375i,  4i) = 10234.5678 : parse_base('10234.5678',  4i) = 227.65625+10.859375i
```

Visual Basic .NET

Translation of: C#
`Imports System.Text Module Module1     Class Complex : Implements IFormattable        Private ReadOnly real As Double        Private ReadOnly imag As Double         Public Sub New(r As Double, i As Double)            real = r            imag = i        End Sub         Public Sub New(r As Integer, i As Integer)            real = r            imag = i        End Sub         Public Function Inv() As Complex            Dim denom = real * real + imag * imag            Return New Complex(real / denom, -imag / denom)        End Function         Public Shared Operator -(self As Complex) As Complex            Return New Complex(-self.real, -self.imag)        End Operator         Public Shared Operator +(lhs As Complex, rhs As Complex) As Complex            Return New Complex(lhs.real + rhs.real, lhs.imag + rhs.imag)        End Operator         Public Shared Operator -(lhs As Complex, rhs As Complex) As Complex            Return New Complex(lhs.real - rhs.real, lhs.imag - rhs.imag)        End Operator         Public Shared Operator *(lhs As Complex, rhs As Complex) As Complex            Return New Complex(lhs.real * rhs.real - lhs.imag * rhs.imag, lhs.real * rhs.imag + lhs.imag * rhs.real)        End Operator         Public Shared Operator /(lhs As Complex, rhs As Complex) As Complex            Return lhs * rhs.Inv        End Operator         Public Shared Operator *(lhs As Complex, rhs As Double) As Complex            Return New Complex(lhs.real * rhs, lhs.imag * rhs)        End Operator         Public Function ToQuaterImaginary() As QuaterImaginary            If real = 0.0 AndAlso imag = 0.0 Then                Return New QuaterImaginary("0")            End If            Dim re = CType(real, Integer)            Dim im = CType(imag, Integer)            Dim fi = -1            Dim sb As New StringBuilder            While re <> 0                Dim rm = re Mod -4                re \= -4                If rm < 0 Then                    rm += 4                    re += 1                End If                sb.Append(rm)                sb.Append(0)            End While            If im <> 0 Then                Dim f = (New Complex(0.0, imag) / New Complex(0.0, 2.0)).real                im = Math.Ceiling(f)                f = -4.0 * (f - im)                Dim index = 1                While im <> 0                    Dim rm = im Mod -4                    im \= -4                    If rm < 0 Then                        rm += 4                        im += 1                    End If                    If index < sb.Length Then                        sb(index) = Chr(rm + 48)                    Else                        sb.Append(0)                        sb.Append(rm)                    End If                    index += 2                End While                fi = f            End If            Dim reverse As New String(sb.ToString().Reverse().ToArray())            sb.Length = 0            sb.Append(reverse)            If fi <> -1 Then                sb.AppendFormat(".{0}", fi)            End If            Dim s = sb.ToString().TrimStart("0")            If s(0) = "." Then                s = "0" + s            End If            Return New QuaterImaginary(s)        End Function         Public Overloads Function ToString() As String            Dim r2 = If(real = -0.0, 0.0, real) 'get rid of negative zero            Dim i2 = If(imag = -0.0, 0.0, imag) 'ditto            If i2 = 0.0 Then                Return String.Format("{0}", r2)            End If            If r2 = 0.0 Then                Return String.Format("{0}i", i2)            End If            If i2 > 0.0 Then                Return String.Format("{0} + {1}i", r2, i2)            End If            Return String.Format("{0} - {1}i", r2, -i2)        End Function         Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString            Return ToString()        End Function    End Class     Class QuaterImaginary        Private Shared ReadOnly twoI = New Complex(0.0, 2.0)        Private Shared ReadOnly invTwoI = twoI.Inv()         Private ReadOnly b2i As String         Public Sub New(b2i As String)            If b2i = "" OrElse Not b2i.All(Function(c) "0123.".IndexOf(c) > -1) OrElse b2i.Count(Function(c) c = ".") > 1 Then                Throw New Exception("Invalid Base 2i number")            End If            Me.b2i = b2i        End Sub         Public Function ToComplex() As Complex            Dim pointPos = b2i.IndexOf(".")            Dim posLen = If(pointPos <> -1, pointPos, b2i.Length)            Dim sum = New Complex(0.0, 0.0)            Dim prod = New Complex(1.0, 0.0)            For j = 0 To posLen - 1                Dim k = Asc(b2i(posLen - 1 - j)) - Asc("0")                If k > 0.0 Then                    sum += prod * k                End If                prod *= twoI            Next            If pointPos <> -1 Then                prod = invTwoI                For j = posLen + 1 To b2i.Length - 1                    Dim k = Asc(b2i(j)) - Asc("0")                    If k > 0.0 Then                        sum += prod * k                    End If                    prod *= invTwoI                Next            End If            Return sum        End Function         Public Overrides Function ToString() As String            Return b2i        End Function    End Class     Sub Main()        For i = 1 To 16            Dim c1 As New Complex(i, 0)            Dim qi = c1.ToQuaterImaginary()            Dim c2 = qi.ToComplex()            Console.Write("{0,4} -> {1,8} -> {2,4}     ", c1, qi, c2)            c1 = -c1            qi = c1.ToQuaterImaginary()            c2 = qi.ToComplex()            Console.WriteLine("{0,4} -> {1,8} -> {2,4}", c1, qi, c2)        Next        Console.WriteLine()        For i = 1 To 16            Dim c1 As New Complex(0, i)            Dim qi = c1.ToQuaterImaginary()            Dim c2 = qi.ToComplex()            Console.Write("{0,4} -> {1,8} -> {2,4}     ", c1, qi, c2)            c1 = -c1            qi = c1.ToQuaterImaginary()            c2 = qi.ToComplex()            Console.WriteLine("{0,4} -> {1,8} -> {2,4}", c1, qi, c2)        Next    End Sub End Module`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i      -1i ->      0.2 ->  -1i
2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
3i ->     20.2 ->   3i      -3i ->   1030.2 ->  -3i
4i ->     20.0 ->   4i      -4i ->   1020.0 ->  -4i
5i ->     30.2 ->   5i      -5i ->   1020.2 ->  -5i
6i ->     30.0 ->   6i      -6i ->   1010.0 ->  -6i
7i -> 103000.2 ->   7i      -7i ->   1010.2 ->  -7i
8i -> 103000.0 ->   8i      -8i ->   1000.0 ->  -8i
9i -> 103010.2 ->   9i      -9i ->   1000.2 ->  -9i
10i -> 103010.0 ->  10i     -10i ->   2030.0 -> -10i
11i -> 103020.2 ->  11i     -11i ->   2030.2 -> -11i
12i -> 103020.0 ->  12i     -12i ->   2020.0 -> -12i
13i -> 103030.2 ->  13i     -13i ->   2020.2 -> -13i
14i -> 103030.0 ->  14i     -14i ->   2010.0 -> -14i
15i -> 102000.2 ->  15i     -15i ->   2010.2 -> -15i
16i -> 102000.0 ->  16i     -16i ->   2000.0 -> -16i```

Wren

Translation of: Go
Library: Wren-complex
Library: Wren-fmt
`import "/complex" for Compleximport "/fmt" for Fmt class QuaterImaginary {    construct new(b2i) {       if (b2i.type != String || b2i == "" || !b2i.all { |d| "0123.".contains(d) } ||           b2i.count { |d| d == "." } > 1) Fiber.abort("Invalid Base 2i number.")        _b2i = b2i    }     // only works properly if 'c.real' and 'c.imag' are both integral    static fromComplex(c) {        if (c.real == 0 && c.imag == 0) return QuaterImaginary.new("0")        var re = c.real.truncate        var im = c.imag.truncate        var fi = -1        var sb = ""        while (re != 0) {            var rem = re % (-4)            re = (re/(-4)).truncate            if (rem < 0) {                rem = 4 + rem                re = re + 1            }            if (rem == -0) rem = 0 // get rid of minus zero            sb = sb + rem.toString + "0"        }        if (im != 0) {            var f = (Complex.new(0, c.imag) / Complex.imagTwo).real            im = f.ceil            f = -4 * (f - im)            var index = 1            while (im != 0) {                var rem = im % (-4)                im = (im/(-4)).truncate                if (rem < 0) {                    rem = 4 + rem                    im = im + 1                }                if (index < sb.count) {                    var sbl = sb.toList                    sbl[index] = String.fromByte(rem + 48)                    sb = sbl.join()                } else {                    if (rem == -0) rem = 0 // get rid of minus zero                    sb = sb + "0" + rem.toString                }                index = index + 2            }            fi = f.truncate        }        if (sb.count > 0) sb = sb[-1..0]        if (fi != -1) {            if (fi == -0) fi = 0 // get rid of minus zero            sb = sb + ".%(fi)"        }        sb = sb.trimStart("0")        if (sb.startsWith(".")) sb = "0" + sb        return QuaterImaginary.new(sb)    }     toComplex {        var pointPos = _b2i.indexOf(".")        var posLen = (pointPos != -1) ? pointPos : _b2i.count        var sum = Complex.zero        var prod = Complex.one        for (j in 0...posLen) {            var k = _b2i.bytes[posLen-1-j] - 48            if (k > 0) sum = sum + prod * k            prod = prod * Complex.imagTwo        }        if (pointPos != -1) {            prod = Complex.imagTwo.inverse            var j = posLen + 1            while (j < _b2i.count) {                var k = _b2i.bytes[j] - 48                if (k > 0) sum = sum + prod * k                prod = prod / Complex.imagTwo                j = j + 1            }        }        return sum    }     toString { _b2i }} var imagOnly = Fn.new { |c| c.imag.toString + "i" } var fmt = "\$4s -> \$8s -> \$4s"Complex.showAsReal = truefor (i in 1..16) {    var c1 = Complex.new(i, 0)    var qi = QuaterImaginary.fromComplex(c1)    var c2 = qi.toComplex    Fmt.write("%(fmt)     ", c1, qi, c2)    c1 = -c1    qi = QuaterImaginary.fromComplex(c1)    c2 = qi.toComplex    Fmt.print(fmt, c1, qi, c2)}System.print()for (i in 1..16) {    var c1 = Complex.new(0, i)    var qi = QuaterImaginary.fromComplex(c1)    var c2 = qi.toComplex    Fmt.write("%(fmt)     ", imagOnly.call(c1), qi, imagOnly.call(c2))    c1 = -c1    qi = QuaterImaginary.fromComplex(c1)    c2 = qi.toComplex    Fmt.print(fmt, imagOnly.call(c1), qi, imagOnly.call(c2))}`
Output:
```   1 ->        1 ->    1       -1 ->      103 ->   -1
2 ->        2 ->    2       -2 ->      102 ->   -2
3 ->        3 ->    3       -3 ->      101 ->   -3
4 ->    10300 ->    4       -4 ->      100 ->   -4
5 ->    10301 ->    5       -5 ->      203 ->   -5
6 ->    10302 ->    6       -6 ->      202 ->   -6
7 ->    10303 ->    7       -7 ->      201 ->   -7
8 ->    10200 ->    8       -8 ->      200 ->   -8
9 ->    10201 ->    9       -9 ->      303 ->   -9
10 ->    10202 ->   10      -10 ->      302 ->  -10
11 ->    10203 ->   11      -11 ->      301 ->  -11
12 ->    10100 ->   12      -12 ->      300 ->  -12
13 ->    10101 ->   13      -13 ->  1030003 ->  -13
14 ->    10102 ->   14      -14 ->  1030002 ->  -14
15 ->    10103 ->   15      -15 ->  1030001 ->  -15
16 ->    10000 ->   16      -16 ->  1030000 ->  -16

1i ->     10.2 ->   1i      -1i ->      0.2 ->  -1i
2i ->     10.0 ->   2i      -2i ->   1030.0 ->  -2i
3i ->     20.2 ->   3i      -3i ->   1030.2 ->  -3i
4i ->     20.0 ->   4i      -4i ->   1020.0 ->  -4i
5i ->     30.2 ->   5i      -5i ->   1020.2 ->  -5i
6i ->     30.0 ->   6i      -6i ->   1010.0 ->  -6i
7i -> 103000.2 ->   7i      -7i ->   1010.2 ->  -7i
8i -> 103000.0 ->   8i      -8i ->   1000.0 ->  -8i
9i -> 103010.2 ->   9i      -9i ->   1000.2 ->  -9i
10i -> 103010.0 ->  10i     -10i ->   2030.0 -> -10i
11i -> 103020.2 ->  11i     -11i ->   2030.2 -> -11i
12i -> 103020.0 ->  12i     -12i ->   2020.0 -> -12i
13i -> 103030.2 ->  13i     -13i ->   2020.2 -> -13i
14i -> 103030.0 ->  14i     -14i ->   2010.0 -> -14i
15i -> 102000.2 ->  15i     -15i ->   2010.2 -> -15i
16i -> 102000.0 ->  16i     -16i ->   2000.0 -> -16i
```