Imaginary base numbers: Difference between revisions

m (comment typo)
Line 310:
</tr>
</table>
 
=={{header|C++}}==
{{trans|C#}}
<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;
}</lang>
{{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|C#|C sharp}}==
1,452

edits