How to resolve the algorithm Imaginary base numbers step by step in the Modula-2 programming language
How to resolve the algorithm Imaginary base numbers step by step in the Modula-2 programming language
Table of Contents
Problem Statement
Imaginary base numbers are a non-standard positional numeral system which uses an imaginary number as its radix. The most common is quater-imaginary with radix 2i. The quater-imaginary numeral system was first proposed by Donald Knuth in 1955 as a submission for a high school science talent search. [Ref.] Other imaginary bases are possible too but are not as widely discussed and aren't specifically named. Task: Write a set of procedures (functions, subroutines, however they are referred to in your language) to convert base 10 numbers to an imaginary base and back. At a minimum, support quater-imaginary (base 2i). For extra kudos, support positive or negative bases 2i through 6i (or higher). As a stretch goal, support converting non-integer numbers ( E.G. 227.65625+10.859375i ) to an imaginary base. See Wikipedia: Quater-imaginary_base for more details. For reference, here are some some decimal and complex numbers converted to quater-imaginary.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Imaginary base numbers step by step in the Modula-2 programming language
Source code in the modula-2 programming language
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.
You may also check:How to resolve the algorithm Almost prime step by step in the zkl programming language
You may also check:How to resolve the algorithm Luhn test of credit card numbers step by step in the Raku programming language
You may also check:How to resolve the algorithm Web scraping step by step in the ToffeeScript programming language
You may also check:How to resolve the algorithm String append step by step in the NS-HUBASIC programming language
You may also check:How to resolve the algorithm Function definition step by step in the Emacs Lisp programming language