Task: Imaginary base numbers




Go: 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
}


func 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))
    }
}




Python: import math
import 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"