Imaginary base numbers: Difference between revisions

Added FreeBASIC
m (→‎{{header|Perl 6}}: fix slightly too aggressive rounding)
(Added FreeBASIC)
 
(47 intermediate revisions by 13 users not shown)
Line 1:
{{draft task}}
 
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 [https://en.wikipedia.org/wiki/Donald_Knuth Donald Knuth] in 1955 as a submission for a high school science talent search. [http://www.fact-index.com/q/qu/quater_imaginary_base.html [Ref.]]
 
''The quater-imaginary numeral system was first proposed by [https://en.wikipedia.org/wiki/Donald_Knuth Donald Knuth] in 1955 as a submission for a high school science talent search. [http://www.fact-index.com/q/qu/quater_imaginary_base.html [Ref.]]''
Other imaginary bases are possible too but are not as widely discussed and aren't named.
 
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 imaginary and back. At a minimum, support quater-imaginary (base 2i).
 
'''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 [https://en.wikipedia.org/wiki/Quater-imaginary_base Wikipedia: Quater-imaginary_base] for more details.
Line 302 ⟶ 310:
</tr>
</table>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F inv(c)
V denom = c.real * c.real + c.imag * c.imag
R Complex(c.real / denom, -c.imag / denom)
 
T QuaterImaginary
:twoI = Complex(0, 2)
:invTwoI = inv(.:twoI)
 
String b2i
 
F (str)
I !re:‘[0123.]+’.match(str) | str.count(‘.’) > 1
assert(0B, ‘Invalid base 2i number’)
.b2i = str
 
F toComplex()
V pointPos = .b2i.findi(‘.’)
V posLen = I (pointPos < 0) {.b2i.len} E pointPos
V sum = Complex(0, 0)
V prod = Complex(1, 0)
L(j) 0 .< posLen
V k = Int(.b2i[posLen - 1 - j])
I k > 0
sum += prod * k
prod *= .:twoI
I pointPos != -1
prod = .:invTwoI
L(j) posLen + 1 .< .b2i.len
V k = Int(.b2i[j])
I k > 0
sum += prod * k
prod *= .:invTwoI
R sum
 
F String()
R String(.b2i)
 
F toQuaterImaginary(c)
I c.real == 0.0 & c.imag == 0.0
R QuaterImaginary(‘0’)
 
V re = Int(c.real)
V im = Int(c.imag)
V fi = -1
V ss = ‘’
L re != 0
(re, V rem) = divmod(re, -4)
I rem < 0
rem += 4
re++
ss ‘’= String(rem)‘0’
I im != 0
V f = c.imag / 2
im = Int(ceil(f))
f = -4 * (f - im)
V index = 1
L im != 0
(im, V rem) = divmod(im, -4)
I rem < 0
rem += 4
im++
I index < ss.len
assert(0B)
E
ss ‘’= ‘0’String(rem)
index = index + 2
fi = Int(f)
ss = reversed(ss)
I fi != -1
ss ‘’= ‘.’String(fi)
ss = ss.ltrim(‘0’)
I ss[0] == ‘.’
ss = ‘0’ss
R QuaterImaginary(ss)
 
L(i) 1..16
V c1 = Complex(i, 0)
V qi = toQuaterImaginary(c1)
V c2 = qi.toComplex()
print(‘#8 -> #8 -> #8 ’.format(c1, qi, c2), end' ‘ ’)
 
c1 = -c1
qi = toQuaterImaginary(c1)
c2 = qi.toComplex()
print(‘#8 -> #8 -> #8’.format(c1, qi, c2))
print()
 
L(i) 1..16
V c1 = Complex(0, i)
V qi = toQuaterImaginary(c1)
V c2 = qi.toComplex()
print(‘#8 -> #8 -> #8 ’.format(c1, qi, c2), end' ‘ ’)
 
c1 = -c1
qi = toQuaterImaginary(c1)
c2 = qi.toComplex()
print(‘#8 -> #8 -> #8’.format(c1, qi, c2))
 
print(‘done’)</syntaxhighlight>
 
{{out}}
<pre>
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
done
</pre>
 
=={{header|C}}==
{{trans|C++}}
<syntaxhighlight lang="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 integral
struct 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;
}</syntaxhighlight>
{{out}}
<pre>( 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)</pre>
 
=={{header|C sharp|C#}}==
<syntaxhighlight lang="csharp">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);
}
}
}
}</syntaxhighlight>
{{out}}
<pre> 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</pre>
 
=={{header|C++}}==
{{trans|C#}}
<syntaxhighlight lang="cpp">#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 integral
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;
}</syntaxhighlight>
{{out}}
<pre> (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)</pre>
 
=={{header|D}}==
{{trans|Kotlin}}
<langsyntaxhighlight Dlang="d">import std.algorithm;
import std.array;
import std.complex;
Line 404 ⟶ 1,254:
foreach (j; posLen+1..b2i.length) {
auto k = (b2i[j] - '0').to!double;
if (k > 0.0) {
sum += prod * k;
}
prod *= invTwoI;
}
Line 441 ⟶ 1,294:
qi = c1.toQuaterImaginary();
c2 = cast(Complex!double) qi;
writefln("%4s -> %8s -> %4s ", c1.re, qi, c2.re);
}
writeln;
Line 448 ⟶ 1,301:
auto qi = c1.toQuaterImaginary;
auto c2 = qi.to!(Complex!double);
writef("%4s4si -> %8s -> %4s4si ", c1.im, qi, c2.im);
c1 = -c1;
qi = c1.toQuaterImaginary();
c2 = cast(Complex!double) qi;
writefln("%4s4si -> %8s -> %4s 4si", c1.im, qi, c2.im);
}
}</langsyntaxhighlight>
{{out}}
<pre> 1 -> 1 -> 1 -1 -> 103 -> -1
Line 473 ⟶ 1,326:
16 -> 10000 -> 16 -16 -> 1030000 -> -16
 
11i -> 10.2 -> 2 1i -11i -> 0.2 -> 0-1i
22i -> 10.0 -> 2 2i -22i -> 1030.0 -> -22i
33i -> 20.2 -> 4 3i -33i -> 1030.2 -> -23i
44i -> 20.0 -> 4 4i -44i -> 1020.0 -> -44i
55i -> 30.2 -> 6 5i -55i -> 1020.2 -> -45i
66i -> 30.0 -> 6 6i -66i -> 1010.0 -> -66i
77i -> 103000.2 -> 8 7i -77i -> 1010.2 -> -67i
88i -> 103000.0 -> 8 8i -88i -> 1000.0 -> -88i
99i -> 103010.2 -> 10 9i -99i -> 1000.2 -> -89i
10 10i -> 103010.0 -> 10 10i -1010i -> 2030.0 -> -1010i
11 11i -> 103020.2 -> 12 11i -1111i -> 2030.2 -> -1011i
12 12i -> 103020.0 -> 12 12i -1212i -> 2020.0 -> -1212i
13 13i -> 103030.2 -> 14 13i -1313i -> 2020.2 -> -1213i
14 14i -> 103030.0 -> 14 14i -1414i -> 2010.0 -> -1414i
15 15i -> 102000.2 -> 16 15i -1515i -> 2010.2 -> -1415i
16 16i -> 102000.0 -> 16 16i -1616i -> 2000.0 -> -1616i</pre>
 
=={{header|FreeBASIC}}==
{{trans|Modula-2}}
<syntaxhighlight lang="vbnet">#define ceil(x) (-((-x*2.0-0.5) Shr 1))
 
Type Complex
real As Double
imag As Double
End Type
 
Type QuaterImaginary
b2i As String
End Type
 
Dim Shared As Complex c1, c2
 
Function StrReverse(Byval txt As String) As String
Dim result As String
For i As Integer = Len(txt) To 1 Step -1
result &= Mid(txt, i, 1)
Next i
Return result
End Function
 
Function ToChar(n As Integer) As String
Return Chr(n + Asc("0"))
End Function
 
Function ComplexMul(lhs As Complex, rhs As Complex) As Complex
Dim As Complex result
result.real = rhs.real * lhs.real - rhs.imag * lhs.imag
result.imag = rhs.real * lhs.imag + rhs.imag * lhs.real
Return result
End Function
 
Function ComplexMulR(lhs As Complex, rhs As Double) As Complex
Dim As Complex result
result.real = lhs.real * rhs
result.imag = lhs.imag * rhs
Return result
End Function
 
Function ComplexInv(c As Complex) As Complex
Dim As Double denom
Dim As Complex result
denom = c.real * c.real + c.imag * c.imag
result.real = c.real / denom
result.imag = -c.imag / denom
Return result
End Function
 
Function ComplexDiv(lhs As Complex, rhs As Complex) As Complex
Return ComplexMul(lhs, ComplexInv(rhs))
End Function
 
Function ComplexNeg(c As Complex) As Complex
Dim As Complex result
result.real = -c.real
result.imag = -c.imag
Return result
End Function
 
Function ComplexSum(lhs As Complex, rhs As Complex) As Complex
Dim As Complex result
result.real = lhs.real + rhs.real
result.imag = lhs.imag + rhs.imag
Return result
End Function
 
Function ToQuaterImaginary(c As Complex) As QuaterImaginary
Dim As Integer re, im, fi, rem_, index
Dim As Double f
Dim As Complex t
Dim As QuaterImaginary result
Dim As String sb
re = Int(c.real)
im = Int(c.imag)
fi = -1
While re <> 0
rem_ = (re Mod -4)
re = re \ (-4)
If rem_ < 0 Then
rem_ = 4 + rem_
re += 1
End If
sb &= ToChar(rem_) & "0"
Wend
If im <> 0 Then
t = ComplexDiv(Type<Complex>(0.0, c.imag), Type<Complex>(0.0, 2.0))
f = t.real
im = Ceil(f)
f = -4.0 * (f - Cdbl(im))
index = 1
While im <> 0
rem_ = im Mod -4
im \= -4
If rem_ < 0 Then
rem_ = 4 + rem_
im += 1
End If
If index < Len(sb) Then
Mid(sb, index + 1, 1) = ToChar(rem_)
Else
sb &= "0" & ToChar(rem_)
End If
index += 2
Wend
fi = Int(f)
End If
sb = StrReverse(sb)
If fi <> -1 Then sb &= "." & ToChar(fi)
sb = Ltrim(sb, "0")
If Left(sb, 1) = "." Then sb = "0" & sb
result.b2i = sb
Return result
End Function
 
Function ToComplex(qi As QuaterImaginary) As Complex
Dim As Integer j, pointPos, posLen, b2iLen
Dim As Double k
Dim As Complex sum, prod
pointPos = Instr(qi.b2i, ".")
posLen = Iif(pointPos = 0, Len(qi.b2i), pointPos - 1)
sum.real = 0.0
sum.imag = 0.0
prod.real = 1.0
prod.imag = 0.0
For j = 0 To posLen - 1
k = Val(Mid(qi.b2i, posLen - j, 1))
If k > 0.0 Then sum = ComplexSum(sum, ComplexMulR(prod, k))
prod = ComplexMul(prod, Type<Complex>(0.0, 2.0))
Next
If pointPos <> 0 Then
prod = ComplexInv(Type<Complex>(0.0, 2.0))
b2iLen = Len(qi.b2i)
For j = posLen + 1 To b2iLen - 1
k = Val(Mid(qi.b2i, j + 1, 1))
If k > 0.0 Then sum = ComplexSum(sum, ComplexMulR(prod, k))
prod = ComplexMul(prod, ComplexInv(Type<Complex>(0.0, 2.0)))
Next
End If
Return sum
End Function
 
Dim As QuaterImaginary qi
Dim As Integer i
For i = 1 To 16
c1.real = Cdbl(i)
c1.imag = 0.0
qi = ToQuaterImaginary(c1)
c2 = ToComplex(qi)
Print c1.real; "i -> "; qi.b2i; " -> "; c2.real; "i";
c1 = ComplexNeg(c1)
qi = ToQuaterImaginary(c1)
c2 = ToComplex(qi)
Print c1.real; "i -> "; qi.b2i; " -> "; c2.real; "i"
Next
Print
For i = 1 To 16
c1.real = 0.0
c1.imag = Cdbl(i)
qi = ToQuaterImaginary(c1)
c2 = ToComplex(qi)
Print c1.imag; "i -> "; qi.b2i; " -> "; c2.imag; "i";
c1 = ComplexNeg(c1)
qi = ToQuaterImaginary(c1)
c2 = ToComplex(qi)
Print c1.imag; "i -> "; qi.b2i; " -> "; c2.imag; "i"
Next
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as Modula-2 entry.</pre>
 
=={{header|Go}}==
{{trans|Kotlin}}
... though a bit shorter as Go has support for complex numbers built into the language.
<syntaxhighlight lang="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
}
 
// only works properly if 'real' and 'imag' are both integral
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))
}
}</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">import Data.Char (chr, digitToInt, intToDigit, isDigit, ord)
import Data.Complex (Complex (..), imagPart, realPart)
import Data.List (delete, elemIndex)
import Data.Maybe (fromMaybe)
 
base :: Complex Float
base = 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 -> Int
digitToIntQI c
| isDigit c = digitToInt c
| otherwise = ord c - ord 'a' + 10
 
shiftRight :: String -> String
shiftRight n
| l == '0' = h
| otherwise = h <> ('.' : [l])
where
(l, h) = (last n, init n)
 
intToDigitQI :: Int -> Char
intToDigitQI i
| i `elem` [0 .. 9] = intToDigit i
| otherwise = chr (i - 10 + ord 'a')
 
fromQItoComplex :: String -> Complex Float -> Complex Float
fromQItoComplex 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 -> Int
getCuid 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 -> String
fromComplexToQI = shiftRight . fmap intToDigitQI . qizip
 
main :: IO ()
main =
putStrLn (fromComplexToQI (35 :+ 23))
>> print (fromQItoComplex "10.2" base)</syntaxhighlight>
{{out}}
<pre>121003.2
0.0 :+ 1.0</pre>
With base = 8i (you may choose any base):
<pre>3z.8
0.0 :+ 7.75</pre>
 
=={{header|J}}==
 
Implementation:
 
<syntaxhighlight lang="j">
ibdec=: {{
0j2 ibdec y
:
digits=. 0,".,~&'36b'@> tolower y -.'. '
(x #. digits) % x^#(}.~ 1+i.&'.')y-.' '
}}"1
 
ibenc=: {{
0j2 ibenc y
:
if.0=y do.,'0' return.end.
sq=.*:x assert. 17 > sq
step=. }.,~(1,|sq) +^:(0>{:@]) (0,sq) #: {.
seq=. step^:(0~:{.)^:_"0
're im0'=.+.y
'im imf'=.(sign,1)*(0,|x)#:im0*sign=.*im0
frac=. ,hfd (imf*|x)-.0 if.#frac do.frac=.'.',frac end.
frac,~(}.~0 i.~_1}.'0'=]) }:,hfd|:0 1|."0 1 seq re,im
}}"0
</syntaxhighlight>
 
This ibdec can decode numbers from complex bases up to 0j6, but this ibenc can only represent digits in complex bases up to 0j4.
 
Examples:
 
<syntaxhighlight lang="j">
(ibenc i:16),.' ',.ibenc j.i:16
1030000 2000
1030001 2010.2
1030002 2010
1030003 2020.2
300 2020
301 2030.2
302 2030
303 1000.2
200 1000
201 1010.2
202 1010
203 1020.2
100 1020
101 1030.2
102 1030
103 0.2
0 0
1 0.2
2 10
3 10.2
10300 20
10301 20.2
10302 30
10303 30.2
10200 103000
10201 103000.2
10202 103010
10203 103010.2
10100 103020
10101 103020.2
10102 103030
10103 103030.2
10000 102000
(ibdec ibenc i:16),:ibdec ibenc j.i:16
_16 _15 _14 _13 _12 _11 _10 _9 _8 _7 _6 _5 _4 _3 _2 _1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
0j_16 0j_15 0j_14 0j_13 0j_12 0j_11 0j_10 0j_9 0j_8 0j_7 0j_6 0j_5 0j_4 0j_3 0j_2 0j_1 0 0j_1 0j2 0j1 0j4 0j3 0j6 0j5 0j8 0j7 0j10 0j9 0j12 0j11 0j14 0j13 0j16
0j4 ibenc 42
10e0a
0j4 ibdec 0j4 ibenc 42
42
</syntaxhighlight>
 
=={{header|Java}}==
{{trans|Kotlin}}
<syntaxhighlight lang="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();
}
}
}</syntaxhighlight>
{{out}}
<pre> 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</pre>
 
=={{header|Julia}}==
{{trans|C#}}
<syntaxhighlight lang="julia">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
true
end
inbase4(s::String) = inbase4(split(s, ""))
 
abstract type ImaginaryBaseNumber <: Number end
 
struct QuaterImaginary <: ImaginaryBaseNumber
cvector::Vector{Char}
isnegative::Bool
end
 
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
qsum
end
 
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()
end
end
 
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()
</syntaxhighlight>{{output}}<pre>
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
</pre>
 
=={{header|Kotlin}}==
Line 494 ⟶ 2,300:
 
As the JDK lacks a complex number class, I've included a very basic one in the program.
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import kotlin.math.ceil
Line 639 ⟶ 2,445:
println(fmt.format(c1, qi, c2))
}
}</langsyntaxhighlight>
 
{{out}}
Line 678 ⟶ 2,484:
</pre>
 
=={{header|Perl 6Modula-2}}==
{{trans|C#}}
<syntaxhighlight lang="modula2">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 '-'
END
END ToChar;
 
PROCEDURE AppendChar(VAR sb : StringBuilder; c : CHAR);
BEGIN
sb.buf[sb.ptr] := c;
INC(sb.ptr);
sb.buf[sb.ptr] := 0C
END AppendChar;
 
PROCEDURE AppendInt(VAR sb : StringBuilder; n : INTEGER);
BEGIN
sb.buf[sb.ptr] := ToChar(n);
INC(sb.ptr);
sb.buf[sb.ptr] := 0C
END 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 t
END Ceil;
 
PROCEDURE Modulus(q,d : INTEGER) : INTEGER;
VAR t : INTEGER;
BEGIN
t := q / d;
RETURN q - d * t
END 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)
END
END 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
END
END 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")
END
END 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 sum
END 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;
 
ReadChar
END ImaginaryBase.</syntaxhighlight>
{{out}}
<pre>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</pre>
 
=={{header|Nim}}==
{{trans|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.
<syntaxhighlight lang="nim">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}"</syntaxhighlight>
 
{{out}}
<pre> 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</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
{{libheader|ntheory}}
<syntaxhighlight lang="perl">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);</syntaxhighlight>
{{out}}
<pre>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</pre>
 
=={{header|Phix}}==
{{trans|Sidef}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">complex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">base2</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">precision</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;"><-</span><span style="color: #000000;">36</span> <span style="color: #008080;">or</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">>-</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"radix out of range (-2..-36)"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"0"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">place</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">upper_bound</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">lower_bound</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">*</span><span style="color: #000000;">upper_bound</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lower_bound</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #008080;">not</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">upper_bound</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">place</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">/</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span><span style="color: #000000;">place</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">while</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">v</span> <span style="color: #008080;">or</span> <span style="color: #000000;">place</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">place</span> <span style="color: #0000FF;">></span> <span style="color: #000000;">precision</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">*</span><span style="color: #000000;">v</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">lower_bound</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">*</span><span style="color: #000000;">v</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">place</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">result</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'.'</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">+</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">></span><span style="color: #000000;">9</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">place</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dot</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">result</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dot</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">result</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">result</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$]}</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">zip</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ld</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ld</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ld</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">complexn</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">precision</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">absrad</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">radix2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">absrad</span><span style="color: #0000FF;"><</span><span style="color: #000000;">2</span> <span style="color: #008080;">or</span> <span style="color: #000000;">absrad</span><span style="color: #0000FF;">></span><span style="color: #000000;">6</span> <span style="color: #008080;">then</span> <span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"base radix out of range"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">re</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">im</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">complex_real</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">complex_imag</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)}</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">re_wh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">re_fr</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">re</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">radix2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">precision</span><span style="color: #0000FF;">),</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">im_wh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">im_fr</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im</span><span style="color: #0000FF;">/</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">radix2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">precision</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">whole</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">zip</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">re_wh</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im_wh</span><span style="color: #0000FF;">))),</span>
<span style="color: #000000;">fraction</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zip</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im_fr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">re_fr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fraction</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">"0"</span> <span style="color: #008080;">then</span> <span style="color: #000000;">whole</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'.'</span><span style="color: #0000FF;">&</span><span style="color: #000000;">fraction</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">whole</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">parse_base</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">str</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">complexn</span> <span style="color: #000000;">fraction</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dot</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dot</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">fr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">-=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">fraction</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fraction</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_power</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">},-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">-=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">fraction</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fraction</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_power</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">},(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">))))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">fraction</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">},</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">7.75</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},{.</span><span style="color: #000000;">25</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- base 2i tests</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- same value, positive imaginary bases</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- same value, negative imaginary bases</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">227.65625</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10.859375</span><span style="color: #0000FF;">},</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},</span> <span style="color: #000080;font-style:italic;">-- larger test value</span>
<span style="color: #0000FF;">{{-</span><span style="color: #000000;">579.8225308641975744</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">5296.406378600824</span><span style="color: #0000FF;">},</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}}</span> <span style="color: #000080;font-style:italic;">-- phix.rules
-- matches output of Sidef and Raku:</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">complexn</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">ibase</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">strv</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">strb</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">parse_base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ibase</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"base(%20s, %2di) = %-10s : parse_base(%12s, %2di) = %s\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">strv</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ibase</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">'"'</span><span style="color: #0000FF;">&</span><span style="color: #000000;">ibase</span><span style="color: #0000FF;">&</span><span style="color: #008000;">'"'</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">strb</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">-- matches output of Kotlin, Java, Go, D, and C#:</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ri</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- real then imag</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">16</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">complexn</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #000000;">i</span><span style="color: #0000FF;">:{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">nc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_neg</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">sc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">snc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nc</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ib</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">inb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">rc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">parse_base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">rnc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">parse_base</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inb</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%4s -&gt; %8s -&gt; %4s %4s -&gt; %8s -&gt; %4s\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">sc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ib</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">snc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">inb</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rnc</span> <span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
Matches the output of Sidef and Raku, except for the final line:
<pre>
base( -579.823-5296.41i, 6i) = phix.rules : parse_base("phix.rules", 6i) = -579.823-5296.41i
</pre>
Also matches the output of Kotlin, Java, Go, D, and C#, except the even entries in the second half, eg:
<pre>
2i -> 10 -> 2i -2i -> 1030 -> -2i
</pre>
instead of
<pre>
2i -> 10.0 -> 2i -2i -> 1030.0 -> -2i
</pre>
ie the unnecessary trailing ".0" are trimmed. (see talk page)
 
=={{header|Python}}==
{{trans|C++}}
<syntaxhighlight lang="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"
</syntaxhighlight>
{{out}}
<pre> (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</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
=== Explicit ===
{{works with|Rakudo|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 here. Note that imaginary number coefficients are stored as floating point numbers in Perl 6Raku so some rounding error may creep in during calculations. The precision these conversion routines use is configurable; we are using 86 <strike>decimal</strike>, um... radicimal(?) places of precision here.
 
Implements minimum, extra kudos and stretch goals.
Note that this implementation can convert any number, not just integers.
 
<syntaxhighlight lang="raku" perl6line>multi sub base ( Real $num, Int $radix where -37 < * < -1, :$precision = -15 ) {
return '0' unless $num;
my $value = $num;
Line 739 ⟶ 3,488:
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;
}</langsyntaxhighlight>
{{out}}
<pre> 0.&base( 2i) = 0 : '0'.&parse-base( 2i) = 0
Line 761 ⟶ 3,510:
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</pre>
 
=== Module ===
{{works with|Rakudo|2020.02}}
 
Using the module [https://modules.raku.org/search/?q=Base%3A%3AAny 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.
 
<syntaxhighlight lang="raku" line>use Base::Any;
 
# TESTING
for 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;
}</syntaxhighlight>
{{out}}
<pre> 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</pre>
=={{header|Ruby}}==
{{works with|Ruby|2.3}}
'''The Functions'''
<syntaxhighlight lang="ruby"># Convert a quarter-imaginary base value (as a string) into a base 10 Gaussian integer.
 
def base2i_decode(qi)
return 0 if qi == '0'
md = qi.match(/^(?<int>[0-3]+)(?:\.(?<frc>[0-3]+))?$/)
raise 'ill-formed quarter-imaginary base value' if !md
ls_pow = md[:frc] ? -(md[:frc].length) : 0
value = 0
(md[:int] + (md[:frc] ? md[:frc] : '')).reverse.each_char.with_index do |dig, inx|
value += dig.to_i * (2i)**(inx + ls_pow)
end
return value
end
 
# Convert a base 10 Gaussian integer into a quarter-imaginary base value (as a string).
 
def base2i_encode(gi)
odd = gi.imag.to_i.odd?
frac = (gi.imag.to_i != 0)
real = gi.real.to_i
imag = (gi.imag.to_i + 1) / 2
value = ''
phase_real = true
while (real != 0) || (imag != 0)
if phase_real
real, rem = real.divmod(4)
real = -real
else
imag, rem = imag.divmod(4)
imag = -imag
end
value.prepend(rem.to_s)
phase_real = !phase_real
end
value = '0' if value == ''
value.concat(odd ? '.2' : '.0') if frac
return value
end</syntaxhighlight>
'''The Task'''
<syntaxhighlight lang="ruby"># Extend class Integer with a string conveter.
 
class Integer
def as_str()
return to_s()
end
end
 
# Extend class Complex with a string conveter (works only with Gaussian integers).
 
class Complex
def as_str()
return '0' if self == 0
return real.to_i.to_s if imag == 0
return imag.to_i.to_s + 'i' if real == 0
return real.to_i.to_s + '+' + imag.to_i.to_s + 'i' if imag >= 0
return real.to_i.to_s + '-' + (-(imag.to_i)).to_s + 'i'
end
end
 
# Emit various tables of conversions.
 
1.step(16) do |gi|
puts(" %4s -> %8s -> %4s %4s -> %8s -> %4s" %
[gi.as_str, base2i_encode(gi), base2i_decode(base2i_encode(gi)).as_str,
(-gi).as_str, base2i_encode(-gi), base2i_decode(base2i_encode(-gi)).as_str])
end
puts
1.step(16) do |gi|
gi *= 0+1i
puts(" %4s -> %8s -> %4s %4s -> %8s -> %4s" %
[gi.as_str, base2i_encode(gi), base2i_decode(base2i_encode(gi)).as_str,
(-gi).as_str, base2i_encode(-gi), base2i_decode(base2i_encode(-gi)).as_str])
end
puts
0.step(3) do |m|
0.step(3) do |l|
0.step(3) do |h|
qi = (100 * h + 10 * m + l).to_s
gi = base2i_decode(qi)
md = base2i_encode(gi).match(/^(?<num>[0-3]+)(?:\.0)?$/)
print(" %4s -> %6s -> %4s" % [qi, gi.as_str, md[:num]])
end
puts
end
end</syntaxhighlight>
{{out}}
Conversions given in the task.
<pre> 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</pre>
{{out}}
From the OEIS Wiki [http://oeis.org/wiki/Quater-imaginary_base].
<pre> 0 -> 0 -> 0 100 -> -4 -> 100 200 -> -8 -> 200 300 -> -12 -> 300
1 -> 1 -> 1 101 -> -3 -> 101 201 -> -7 -> 201 301 -> -11 -> 301
2 -> 2 -> 2 102 -> -2 -> 102 202 -> -6 -> 202 302 -> -10 -> 302
3 -> 3 -> 3 103 -> -1 -> 103 203 -> -5 -> 203 303 -> -9 -> 303
10 -> 2i -> 10 110 -> -4+2i -> 110 210 -> -8+2i -> 210 310 -> -12+2i -> 310
11 -> 1+2i -> 11 111 -> -3+2i -> 111 211 -> -7+2i -> 211 311 -> -11+2i -> 311
12 -> 2+2i -> 12 112 -> -2+2i -> 112 212 -> -6+2i -> 212 312 -> -10+2i -> 312
13 -> 3+2i -> 13 113 -> -1+2i -> 113 213 -> -5+2i -> 213 313 -> -9+2i -> 313
20 -> 4i -> 20 120 -> -4+4i -> 120 220 -> -8+4i -> 220 320 -> -12+4i -> 320
21 -> 1+4i -> 21 121 -> -3+4i -> 121 221 -> -7+4i -> 221 321 -> -11+4i -> 321
22 -> 2+4i -> 22 122 -> -2+4i -> 122 222 -> -6+4i -> 222 322 -> -10+4i -> 322
23 -> 3+4i -> 23 123 -> -1+4i -> 123 223 -> -5+4i -> 223 323 -> -9+4i -> 323
30 -> 6i -> 30 130 -> -4+6i -> 130 230 -> -8+6i -> 230 330 -> -12+6i -> 330
31 -> 1+6i -> 31 131 -> -3+6i -> 131 231 -> -7+6i -> 231 331 -> -11+6i -> 331
32 -> 2+6i -> 32 132 -> -2+6i -> 132 232 -> -6+6i -> 232 332 -> -10+6i -> 332
33 -> 3+6i -> 33 133 -> -1+6i -> 133 233 -> -5+6i -> 233 333 -> -9+6i -> 333</pre>
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">func base (Number num, Number radix { _ ~~ (-36 .. -2) }, precision = -15) -> String {
num || return '0'
 
Line 834 ⟶ 3,770:
printf("base(%20s, %2si) = %-10s : parse_base(%12s, %2si) = %s\n",
v, r.im, ibase, "'#{ibase}'", r.im, parse_base(ibase, r).round(-8))
})</langsyntaxhighlight>
{{out}}
<pre>
Line 856 ⟶ 3,792:
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
</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">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</syntaxhighlight>
{{out}}
<pre> 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</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-complex}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./complex" for Complex
import "./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 = true
for (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))
}</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
2,122

edits