179 lines
5.8 KiB
Java
179 lines
5.8 KiB
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());
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
}
|