Imaginary base numbers: Difference between revisions
Content added Content deleted
m (comment typo) |
|||
Line 310: | Line 310: | ||
</tr> |
</tr> |
||
</table> |
</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}}== |
=={{header|C#|C sharp}}== |