Task: Imaginary base numbers


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;
}


QuaterImaginary 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;
}




Java: 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());
        }

        
        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;  
            double imag2 = imag == -0.0 ? 0.0 : imag;  
            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();
        }
    }
}