Moniulotteinen 2D-algebra

Seuraa 
Viestejä45973
Liittynyt3.9.2015

Eräs minun elämänkäänteisiin suuresti vaikuttanut henkilö totesi: Matematiikka ei oikeastaan enää kovin paljon kiinnosta, koska se on vieraantunut niin voimakkaasti arkipäiväisistä tarpeista.

Tämän voin allekirjoittaa myös omalta osaltani, joskin saan jokapäiväisessä työssäni mallintaa muun muassa robotiikkaan liittyviä liikeratoja, yms. puhtaasti arkipäiväisiä probleemoja.

Kuitenkin, sovelletun matematiikan mahdollisuudet (ja myös lukuteoreettiset kysymykset) ovat toisinaan enemmän mielenkiinnon kohteena, kuin työhöni liittyvät asiat. Silloin on ikään kuin työn touhussa, vaikka algoritmi etsiikin/tutkiikin esimerkiksi kahden yhteyttä suhteessa muihin alkulukuihin.

Kompleksiluvuista saattoi lopulta havaita, että ne yleistyvät käsittämään myös ns. kompleksiavaruudet ilman ristiriitoja. Kenties niiden lukuteoreettisesti mielenkiintoisin yhteys on:

|e^(ai+bj+ck+...)|=1

Kompleksiluvut asettuvat tuon takaisinkytkennän osajoukoksi edelleen symmetrialla:

|e^ai|=1

Mutta, reaaliluvut voi myös laajentaa toiseen dimensioon, jolloin puhdas 2D-reaaliluku on paikka lukutasossa (x, y). Ristiriidat kaikkoavat, kun laskutoimitukset suoritetaan redusoimattomana ottamatta kantaa symbolisiin tulkintoihin positiivisesta, negatiivisesta ja x-tiivisistä suunnista.

Edelleen 2D-reaaliluvut ovat yhtä epätäydellisiä, kuin reaaliluvutkin. 2D-reaaliluvut tarvitsevat rinnalleen 2D-imaginaariluvut, jolloin symmetria täydentyy, kuten kompleksiluvuillakin. Jälleen osajoukko. 2D-kompleksilukujen osajoukkona on kompleksiluvut ja niihin liittyvät algebran aksioomat.

Mikään ei edelleenkään estä laajentamasta 2D-symmetriaa 4D:ksi, tai vieläkin etäisemmäksi. Luonto on kuitenkin vastakohtia. Siksi myös lukuteoriassa on vielä joskus pakko löytyä se syy-seuraus, jossa vaa’an toisella puolella on 2 ja toisella puolella loput muut äärettömän monta paritonta alkulukua.

Mene ja tiedä. Mutta se on yksinkertainen. Miksi niin yksinkertainen. Monimutkaisuus on ehkä vain illuusio, joka on verhoutunut (pseudo-)kaaokseen.

Kommentit (8)

Vierailija
_jone_
Mutta, reaaliluvut voi myös laajentaa toiseen dimensioon, jolloin puhdas 2D-reaaliluku on paikka lukutasossa (x, y). Ristiriidat kaikkoavat, kun laskutoimitukset suoritetaan redusoimattomana ottamatta kantaa symbolisiin tulkintoihin positiivisesta, negatiivisesta ja x-tiivisistä suunnista.

Miten nuo operaatiot sitten kaiken kaikkeaan suoritetaan redusoimattomina?

-torstai

Vierailija
torstai
Miten nuo operaatiot sitten kaiken kaikkeaan suoritetaan redusoimattomina?

Edit: Niin, ja olisihan tuota voinut korostaa vähän enemmän, että tuo abstraktiosekoilu positiivisen, negatiivisen, yms. tulkintojen kanssa pääsee kunnolla oikeuksiinsa vasta i, j, ja k-olioilla. real2d:ssä on sen vuoksi mukana parittomat alkiot, vaikka niitä ei oikeastaan käytetä lainkaan.

Minun mielestä matemaattinen formalismi on joiltakin osin melko puutteellinen ja vaikeaselkoinen verrattuna esimerkiksi C:hen.

Ehkä jossain vaiheessa tulevaisuudessa tarpeesta syntyy tiedekunta - tietokonematematiikka. Oppisuunta keskittyy tietokoneella sovellettuun matematiikkaan ja yhtä lailla lukuteoreettisiin kysymyksiin. Tietokone on pohjimmiltaan väsymätön ja tehokas työjuhta, jolla asioiden ja ilmiöiden tutkiminen on entistä verkkaisempaa.

Mutta asiaan. Tuo redusointitarve kumpuaa siitä, että positiivinen ja negatiivinen ovat itsessään symbolisia käsitteitä paikasta suhteessa sovittuun referenssipisteeseen. Tietokone ei pysty rakentamaan logiikkaansa abstraktioiden päälle. Sen tähden tietokone heivasi ne toissijaisiksi. Tästä huolimatta tietokone voi kuitenkin kertoa tuloksensa ihmiselle abstraktisilla ’+’ ja ’-’ merkeillä. Hyvä niin.

Käytännön kannalta 2D-reaaliluvun operaattorit on suoraviivaisinta toteuttaa neljällä alkiolla, jossa itse arvo on parillisissa alkioissa. Tietokone käyttää/käyttäköön parittomia alkioita abstraktiosekoilun väliaikaiseen poistamiseen ennen operaatiota. Tietokone palauttaa abstraktion ihmisen tulkitsemaan muotoon automaattisesti jokaisen operaation suorittamisen jälkeen.

Seuraavassa 2D-reaaliluvun lyhyt olio, jossa yritän esimerkeillä hälventää redusointiin liittyvää hämmennystä.

[code:1wb1b3oq]#include
#include

class real2d
{
public:

double e[4];

real2d(void);

real2d(int);
real2d(int, int);

real2d(double);
real2d(double, double);

friend double abs(real2d);
friend void print(real2d);
friend real2d reduse(real2d);
friend real2d operator-(real2d);

friend real2d operator+(real2d, real2d);
friend real2d operator-(real2d, real2d);

friend real2d operator*(real2d, real2d);
friend real2d operator/(real2d, real2d);

friend real2d operator*(double, real2d);
friend real2d operator/(real2d, double);

friend real2d operator*(real2d, double);
friend real2d operator/(double, real2d);
};[/code:1wb1b3oq]
Luokkamäärittely pitää sisällään perusoperaatiot, joilla esimerkiksi sarjojen avulla voi toteuttaa sinit, cosinit, logaritmit, yms. tarpeelliset funktiot.

[code:1wb1b3oq]real2d::real2d(double a)
{
e[0]=a;
e[1]=e[2]=e[3]=0;
}

real2d::real2d(double a, double b)
{
e[0]=a; e[2]=b;
e[1]=e[3]=0.00;
}

real2d::real2d(int a)
{
*this=real2d((double)a);
}

real2d::real2d(int a, int b)
{
*this=real2d((double)a, (double)b);
}

real2d::real2d(void)
{
*this=real2d((double)0);
}[/code:1wb1b3oq]
Muodostimiin ei oikeastaan liity mitään erikoista verrattuna reaalilukuihin. Ainut on toisen reaali-alkion antomahdollisuus.

Esimerkkejä muodostimien käytöstä:

[code:1wb1b3oq]real2d a(2);
real2d b(-2);
real2d c(-2, 3);
real2d d(-2, -3);
real2d e(5.0);
real2d f(7.11, -13.17);
real2d sum=a+b-c+d+e-f;
real2d tmp;[/code:1wb1b3oq]

Redusointi vähentää ensin parittomat alkiot parillisiin alkioihin, ja nollaa ne sen jälkeen. Redusoinnin myötä luku palautuu ihmisen käsitemaailmaan.

[code:1wb1b3oq]real2d reduse(real2d a)
{
a.e[0]-=a.e[1];
a.e[2]-=a.e[3];
a.e[1]=a.e[3]=0;
return (real2d)a;
}[/code:1wb1b3oq]

Itseisarvo on tärkeä funktio, ja ensimmäinen indikaattori, onko substanssi lehmän perseestä vai ei. Millä tahansa toimivalla sontaläjällä on aina oltava algebrallinen ominaisuus:

|a| * |b| = |a*b|

Reaaliluvut ovat 2D-reaaliluvun osajoukko. Toisekseen tietokone on omissa havainnoissaan päätynyt syy-seuraus symmetrioiden osalta tasan siihen logiikkaan, joka reaaliluvuilla on.

[code:1wb1b3oq]double abs(real2d a)
{
a=reduse(a);
return fabs(a.e[0]-a.e[2]);
}[/code:1wb1b3oq]
Esim.

[code:1wb1b3oq]real2d a(2.0, -3.5);
real2d b(-7.11, 13.17);
real2d c=a*b;

printf("%0.7f\n", abs(a));
printf("%0.7f\n", abs(b));
printf("%0.7f <=> %0.7f\n", abs(a*b), abs(a)*abs(b));[/code:1wb1b3oq]
Tulostuu:
[code:1wb1b3oq]5.5000000
20.2800000
111.5400000 <=> 111.5400000[/code:1wb1b3oq]

Yhteen ja vähennyslasku käy lyhyesti:

[code:1wb1b3oq]real2d operator-(real2d a)
{
for (int i=0; i<4; i++)
a.e[i]=-a.e[i];
return reduse(a);
}

real2d operator+(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]+=b.e[i];
return reduse(a);
}

real2d operator-(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]-=b.e[i];
return reduse(a);
}[/code:1wb1b3oq]
Esim.

[code:1wb1b3oq]real2d a(2.0, -3.5);
real2d b(-7.11, 13.17);
real2d c=a+b;
real2d r=-a-b+c;

print(c);
print(r);[/code:1wb1b3oq]
c ja r saavat arvot:
[code:1wb1b3oq]c=(-5.1100000, 9.6700000)
r=(0.0000000, 0.0000000)[/code:1wb1b3oq]

Kertolasku silmukoidaan latinalaisella neliöllä. Redusoimattomassa kertolaskussa reaaliluvun logiikka käy 2*2 -latinalaisella neliöllä. Latinalaisissa 2^n neliöissä pienemmät ovat aina suurempien neliöiden aitoja osajoukkoja.

Jakolasku suoritetaan takaperoisesti. Ensin a/b=c. Sen jälkeen haetaan luku, jolla c*b=a. Tästä generoituu yksinkertainen neljän tuntemattoman lineaarinen yhtälöryhmä, joka sitten ratkaistaan Gaussin eliminointimenetelmällä.

[code:1wb1b3oq]real2d operator*(real2d a, real2d b)
{
real2d t(0.0);
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
t.e[i^j]+=a.e[i]*b.e[j];
return reduse(t);
}

real2d operator/(real2d x, real2d y)
{
double X[4];
double K[4*4+4];

for (int n=0, p=0; n<4; n++)
{
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
{
if (n == (i^j))
{
K[p]=y.e[j]; ++p;
}
}
K[p]=x.e[n]; ++p;
}

// gsolve ratkaisee lineaarisen yhtälöryhmän
// Gaussin eliminointimenetelmällä...
int gsolve(double*, double*, int);

gsolve(X, K, 4);
return reduse(*(real2d*)X);
}

void swapRows(double *a, double *b, int n)
{
for (int i=0; i
{
double tmp=a[i];
a[i]=b[i];
b[i]=tmp;
}
}

int gsolve(double *X, double *f, int n)
{
double k, J;
double *max, *mux;
int i, j, x, M=(int)n+1;

for (i=0; i
{
max=f+i+i*M;
for (j=i+0x01; j < n; j++)
if (fabs(*(mux=f+i+j*M))>fabs(*max)) max=mux;

if (max!=(mux=f+i+i*M))
swapRows(max, mux, M-i);

if (fabs(J=f[i+i*M])<(double)1e-20)
return 0; /* eipä ole ratkaisuva */

for (j=i+1; j
{
if (f[i+j*M])
{
k=-f[i+j*M]/J;
for (x=i+1; x
f[x+j*M]=f[x+j*M]+k*f[x+i*M];
}
}
}

for (i=n-1; i>=0; i--)
{
k=(double)f[n+i*M];
for (j=n-1; j > i; j--)
k=k-(double)(X[j]*f[j+i*M]);

if (fabs(J=f[i+i*M])<(double)1e-20)
return 0; /* eipä ole ratkaisua */
else X[i]=k/J; /* onpa ratkaisu */
}

return 1;
}[/code:1wb1b3oq]
Esim.

[code:1wb1b3oq]real2d a(2.0, -3.5);
real2d b(-7.11, 13.17);
real2d c=a*b;

print(c);
print(c/b);[/code:1wb1b3oq]
Tietokoneen tuloste operaatioista on:

[code:1wb1b3oq](-60.3150000, 51.2250000)
(2.0000000, -3.5000000)[/code:1wb1b3oq]

Lopuksi on vielä muutamia yksinkertaistavia apufunktioita:

[code:1wb1b3oq]real2d operator*(double k, real2d b)
{
real2d a(k);
return a*b;
}

real2d operator/(real2d a, double k)
{
real2d b(k);
return a/b;
}

real2d operator*(real2d a, double k)
{
real2d b(k);
return a*b;
}

real2d operator/(double k, real2d b)
{
real2d a(k);
return a/b;
}

void print(real2d a)
{
a=reduse(a);
printf("(%0.21f, %0.21f)\n", a.e[0], a.e[2]);
}[/code:1wb1b3oq]

2D-imaginaariluvut eivät ole juuri real2d:tä kummempia. Sama vielä yhtenäisenä koodiliitteenä, jonka pitäisi olla likimain painovirheetön. Koodi kääntyy ongelmitta jokaisessa C++ kääntäjässä. Pienellä main:illa pääsee helposti kiinni noihin lukuihin ja katsomaan esimerkiksi sarjojen tuloksia.

[code:1wb1b3oq]#include
#include

class real2d
{
public:

double e[4];

real2d(void);

real2d(int);
real2d(int, int);

real2d(double);
real2d(double, double);

friend double abs(real2d);
friend void print(real2d);
friend real2d reduse(real2d);
friend real2d operator-(real2d);

friend real2d operator+(real2d, real2d);
friend real2d operator-(real2d, real2d);

friend real2d operator*(real2d, real2d);
friend real2d operator/(real2d, real2d);

friend real2d operator*(double, real2d);
friend real2d operator/(real2d, double);

friend real2d operator*(real2d, double);
friend real2d operator/(double, real2d);
};

real2d::real2d(double a)
{
e[0]=a;
e[1]=e[2]=e[3]=0;
}

real2d::real2d(double a, double b)
{
e[0]=a; e[2]=b;
e[1]=e[3]=0.00;
}

real2d::real2d(int a)
{
*this=real2d((double)a);
}

real2d::real2d(int a, int b)
{
*this=real2d((double)a, (double)b);
}

real2d::real2d(void)
{
*this=real2d((double)0);
}

real2d reduse(real2d a)
{
a.e[0]-=a.e[1];
a.e[2]-=a.e[3];
a.e[1]=a.e[3]=0;
return (real2d)a;
}

double abs(real2d a)
{
a=reduse(a);
return fabs(a.e[0]-a.e[2]);
}

real2d operator-(real2d a)
{
for (int i=0; i<4; i++)
a.e[i]=-a.e[i];
return reduse(a);
}

real2d operator+(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]+=b.e[i];
return reduse(a);
}

real2d operator-(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]-=b.e[i];
return reduse(a);
}

real2d operator*(real2d a, real2d b)
{
real2d t(0.0);
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
t.e[i^j]+=a.e[i]*b.e[j];
return reduse(t);
}

real2d operator/(real2d x, real2d y)
{
double X[4];
double K[4*4+4];

for (int n=0, p=0; n<4; n++)
{
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
{
if (n == (i^j))
{
K[p]=y.e[j]; ++p;
}
}
K[p]=x.e[n]; ++p;
}

// gsolve ratkaisee lineaarisen yhtälöryhmän
// Gaussin eliminointimenetelmällä...
int gsolve(double*, double*, int);

gsolve(X, K, 4);
return reduse(*(real2d*)X);
}

void swapRows(double *a, double *b, int n)
{
for (int i=0; i
{
double tmp=a[i];
a[i]=b[i];
b[i]=tmp;
}
}

int gsolve(double *X, double *f, int n)
{
double k, J;
double *max, *mux;
int i, j, x, M=(int)n+1;

for (i=0; i
{
max=f+i+i*M;
for (j=i+0x01; j < n; j++)
if (fabs(*(mux=f+i+j*M))>fabs(*max)) max=mux;

if (max!=(mux=f+i+i*M))
swapRows(max, mux, M-i);

if (fabs(J=f[i+i*M])<(double)1e-20)
return 0; /* eipä ole ratkaisuva */

for (j=i+1; j
{
if (f[i+j*M])
{
k=-f[i+j*M]/J;
for (x=i+1; x
f[x+j*M]=f[x+j*M]+k*f[x+i*M];
}
}
}

for (i=n-1; i>=0; i--)
{
k=(double)f[n+i*M];
for (j=n-1; j > i; j--)
k=k-(double)(X[j]*f[j+i*M]);

if (fabs(J=f[i+i*M])<(double)1e-20)
return 0; /* eipä ole ratkaisua */
else X[i]=k/J; /* onpa ratkaisu */
}

return 1;
}

real2d operator*(double k, real2d b)
{
real2d a(k);
return a*b;
}

real2d operator/(real2d a, double k)
{
real2d b(k);
return a/b;
}

real2d operator*(real2d a, double k)
{
real2d b(k);
return a*b;
}

real2d operator/(double k, real2d b)
{
real2d a(k);
return a/b;
}

void print(real2d a)
{
a=reduse(a);
printf("(%0.7f, %0.7f)\n", a.e[0], a.e[2]);
}

void main(void)
{
real2d a(2.0, -3.5);
real2d b(-7.11, 13.17);
real2d c=a*b;

print(c);
print(c/b);
}[/code:1wb1b3oq]

Vierailija

Ok. Ymmärsin operaatiot kohtalaisen hyvin, mutta jakolaskun ja gsolven sisäistäminen vaatii vielä vähän pään raapimista.

_jone_
Pienellä main:illa pääsee helposti kiinni noihin lukuihin ja katsomaan esimerkiksi sarjojen tuloksia.

Mielenkiintoinen symmetria. Lukutasossa symmetria asettuu jotenkin 45 asteen kulmaan. Sen myötä ymmärtäisin, että kun reaaliluvut ovat tuon 2D-reaaliluvun rajatapaus, 45 astetta on luonnollinen seuraus, koska imaginaariakseli on jo 90 asteen kulmassa?

Tein kuitenkin pienen testin. Piirsin punaisen pisteen, jos neliöjuurelle ei löytynyt 2D-reaalilukuista ratkaisua. Jos sille löytyi ratkaisut, väritin vihreän pisteen. Kun lukutason vaaka- ja pystyakseli ovat jostain miinus n:stä plus n:ään, symmetria asettuu aina kuvan/avatarin mukaisella tavalla. Pitää tässä ajan kanssa perehtyä tuohon lukutasoon enemmän.

-torstai

Vierailija
_jone_
Siksi myös lukuteoriassa on vielä joskus pakko löytyä se syy-seuraus, jossa vaa’an toisella puolella on 2 ja toisella puolella loput muut äärettömän monta paritonta alkulukua.

2D-reaaliluvuilla alkulukuihin näyttää liittyvän hämmentävän täydellinen symmetria. Ensimmäisen alkuluvun 2 yhteys muihin äärettömän moneen parittomaan alkulukuun on käsin kosketeltavaa. Ehkä, ehkä ymmärsin siitä aavistuksen.

Ilmeisesti esim. alkulukuihin perustuvat salausmetodit saattavat olla loppujen lopuksi aika heikolla pohjalla, jos ne osoittautuvat joksikin alkeelliseksi syy-seuraus kaavaksi. Monimutkaisuus on mitä ilmeisemmin pseudo-kaaokseen verhoutunut illuusio. Kirjoitit toisaalla:

_jone_
Pääsin perehtymään joskus vuonna 2000 muu muassa muukompleksisiin fraktaalirakenteisiin ja muukompleksisiin Newtonin prosesseihin, yms.

Olen hiki hatussa yrittänyt johtaa 2D-reaaliluvuista 2D-kompleksilukuja i, j, ja k olioineen. i on selvä tapaus, mutta j- ja k-oliot eivät avaudu. Fraktaaligeometria on aina ollut erityisen mielenkiintoista. Ellei olisi suurta vaivaa, voisitko vähän neuvoa, miten 2D-kompleksiluvutkin saisi kokonaisuudessaan pelaamaan ristiriidattomasti.

-torstai

Vierailija

No, tällä palstalla on moneenkin otteeseen painotettu, että foorumilla on tarkoitus keskustella tieteestä, ei tehdä sitä. Karvas totuus on, että nykyajan tiedeyhteisö on uskonnollistunut. Näen sen jäsenistön toinen toistaan lipevimpinä pappeina, jotka kilvan nuoleskelevat ylempiään. Riittävän pitkäjänteinen mielistely palkitaan sitten lopuksi tavalla tai toisella.

Yököttää. Minäkin muutuin. Alkuperäinen voimakas halu saada jotain aikaan muuttui vuosien saatossa puhtaaksi kilpailuksi itsensä kanssa. Se, mitä ja minkälaista tunnetta itsensä voittaminen tarkalleen ottaen tarkoittaa, ei ole enää verbalisoitavissa. Sen voi vain kokea. Kun aika juoksee kohti loppuaan, vertailupohja suppenee lopulta omaan itseensä.

Mutta kysymykseesi. Minkä tahansa 2^n dimensioisen reaaliluvun vastinsymmetria toteutuu aina käänteisellä latinalaisella neliöllä. (Reaalinen suhteessa algebran aksiomeihin käy siis ristiriidattomasti latinalaisella neliöllä.) Moniulotteisuus on puolestaan ehyen 2^n kompleksiluvun variointi koko ympyrään, eli piihin.

2D-kompleksiluvussa on luonnollisesti neljä 2D-realikuista alkiota. Olkoot ne esim. r, i, j ja k. Käänteinen latinalainen neliön generoi esim. kahden 2D-kompleksiluvun a ja b kertolaskun reaaliarvon tulosäännöksi mössön:

[code:ze146e8r]complex2d operator*(complex2d a, complex2d b)
{
complex2d c(0);

c.r = real2d(1,0,0,0)*a.r*b.r + real2d(0,1,0,0)*a.i*b.i
+ real2d(0,0,1,0)*a.j*b.j + real2d(0,0,0,1)*a.k*b.k;

c.i = real2d(1,0,0,0)*a.r*b.i + ...

c.j = real2d(1,0,0,0)*a.r*b.j + ...

c.k = real2d(1,0,0,0)*a.r*b.k + ...

return c;
}[/code:ze146e8r]
Samalla yksinkertaisuudella käänteinen latinalainen neliö generoi i, j, ja k-olioiden tulosäännöt. Tarvitseeko sitä ymmärtää? Ei, sillä erkkikään ei voisi enää ymmärtää juuri enempää, kuin abstraktilla tasolla algebran aksioomat ja algebran metodit. Varsinkin sarjoilla, funktioapproksimaatioilla, yms. algebrallisilla faktoilla on helppo todeta, että jokin substanssi toimii, tai ei toimi.

Ymmärtäminen on minun mielestä yksinkertaisuuden ja selkeyden ymmärtämistä, ei esim. sitä suunnatonta sontamäärää, jota mm. akateeminen maailma yrittää tunkee opiskelijoiden toisesta korvasta sisään, ja joka sitten kuitenkin pursuaa toisesta päästä jossain vaiheessa ulos.

Vierailija

Ahaa, nyt ymmärsin tuon maailmanlopun koodiksi väännetyn jakolaskun ajatuskulun. Kysymyshän on vain Gaussin eliminointimenetelmästä (kuten mainitsit), mutta käsittelet 2D-taulukkoa 1D:nä, joka sekoitti pahasti pakan.

Olkoon nyt jakolasku A / B = C
Tästä seuraa kääntäen, että C * B = A
Jos toimitetaan 2D-reaalilukuinen jakolasku A=(3, 7) ja B=(6, 4), saadaan lineaarinen yhtälöryhmä:

[code:133osz0d]6a + 0b + 4c + 0d = 3

0a + 6b + 0c + 4d = 0

4a + 0b + 6c + 0d = 7

0a + 4b + 0c + 6d = 0

[/code:133osz0d]
Josta ratkaistuna:

[code:133osz0d]a =-0.5
b = 0.0
c = 1.5
d = 0.0
[/code:133osz0d]
Kun nyt saatu tulos kerrotaan B:llä saadaan A, niin kuin pitääkin. Yhtälöryhmän perusteella jakolasku on pakko suorittaa redusoimattomana, koska jokaisen sarakkeen tuntemattomilla on kertoimet.

PS. Olisiko suurta vaivaa laittaa se 2D-kompleksiolion koodi tänne, koska ainakaan minulle ei kerta kaikkiaan avaudu, miten saisin olion toimimaan ristiriidattomasti i, j, ja k olioilla.

-torstai

Vierailija
torstai
Piirsin punaisen pisteen, jos neliöjuurelle ei löytynyt 2D-reaalilukuista ratkaisua. Jos sille löytyi ratkaisut, väritin vihreän pisteen. Kun lukutason vaaka- ja pystyakseli ovat jostain miinus n:stä plus n:ään, symmetria asettuu aina kuvan/avatarin mukaisella tavalla.

Epälineaaristen syiden kuvaaminen toisessa potenssissa on seurausta latinalaisen neliön lävistäjästä, joka sallii 2D-kompleksiluvuilla neljä neliöjuurta joka luvulle (neljä syytä per seuraus. ks. avatar).

Ei tuo tulkintasi sinällään kovin paljon vääräkään ole, mutta 2D-kompleksiluvun reaaliosa pystyy antamaan ratkaisut vain lukutason neljäsosalle. Kuitenkin, kuten sanoin, kysymys on nyt enemmän sellaisesta hiusten halkomisesta ja äärimmäisestä algebran aksioomien kiinni pitämisestä.

Plaah. Seuraavassa on tuo koodimössö ilman moniulotteista takaisinkytkentää:

[code:hdkwnpbo]#include
#include

typedef long double lreal;
#define lr(cx) (lreal)(cx)

class real2d
{
public:

lreal e[4];
real2d(void);

real2d(int);
real2d(int, int);
real2d(int, int, int, int);

real2d(lreal);
real2d(lreal, lreal);

friend int ifpos(real2d);
friend lreal abs(real2d);
friend void print(real2d);

friend real2d sqrt(real2d);
friend real2d reduse(real2d);
friend real2d operator-(real2d);

friend real2d operator+(real2d, real2d);
friend real2d operator-(real2d, real2d);

friend real2d operator*(real2d, real2d);
friend real2d operator/(real2d, real2d);

friend real2d operator*(lreal, real2d);
friend real2d operator/(real2d, lreal);

friend real2d operator*(real2d, lreal);
friend real2d operator/(lreal, real2d);

/* mgn = luvun suuruus */
friend lreal mgn(real2d);
friend real2d ln(real2d);
friend real2d exp(real2d);
friend real2d sin(real2d);
friend real2d cos(real2d);
friend real2d pow(real2d, int);
friend real2d pow(real2d, lreal);
friend real2d pow(real2d, real2d);
};

real2d::real2d(lreal a)
{
e[0]=a; e[1]=0;
e[2]=e[3]=0.00;
}

real2d::real2d(lreal a, lreal b)
{
e[0]=a; e[2]=b;
e[1]=e[3]=0.00;
}

real2d::real2d(int a)
{
*this=real2d((lreal)a);
}

real2d::real2d(int a, int b)
{
*this=real2d((lreal)a, (lreal)b);
}

real2d::real2d(int a, int b, int c, int d)
{
e[0]=a; e[1]=b;
e[2]=c; e[3]=d;
}

real2d::real2d(void)
{
*this=real2d((lreal)0);
}

real2d reduse(real2d a)
{
a.e[0]-=a.e[1];
a.e[2]-=a.e[3];
a.e[1]=a.e[3]=0;
return (real2d)a;
}

lreal abs(real2d a)
{
lreal x = a.e[0]-a.e[1];
lreal y = a.e[2]-a.e[3];
return lr(fabsl(x - y));
}

lreal mgn(real2d a)
{
lreal x=a.e[0]-a.e[1];
lreal y=a.e[2]-a.e[3];
return fabsl(x)+fabsl(y);
}

int ifpos(real2d a)
{
lreal x=a.e[0]-a.e[1];
lreal y=a.e[2]-a.e[3];

if (x>=0.0)
{
return fabsl(y)<=x? 1: 0;
}
else
{
return 0;
}
}

real2d operator-(real2d a)
{
for (int i=0; i<4; i++)
a.e[i]=-a.e[i];
return reduse(a);
}

real2d operator+(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]+=b.e[i];
return reduse(a);
}

real2d operator-(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]-=b.e[i];
return reduse(a);
}

real2d operator*(real2d a, real2d b)
{
real2d t(0.0);
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
t.e[i^j]+=a.e[i]*b.e[j];
return reduse(t);
}

real2d operator/(real2d x, real2d y)
{
lreal X[4];
lreal K[4*4+4];

for (int n=0, p=0; n<4; n++)
{
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
{
if (n == (i^j))
{
K[p]=y.e[j]; ++p;
}
}
K[p]=x.e[n]; ++p;
}

// gsolve ratkaisee lineaarisen yhtälöryhmän
// Gaussin eliminointimenetelmällä...
int gsolve(lreal*, lreal*, int);

gsolve(X, K, 4);
lreal a=X[0]-X[1];
lreal b=X[2]-X[3];
return real2d(a, b);
}

void swapRows(lreal *a, lreal *b, int n)
{
for (int i=0; i
{
lreal tmp=a[i];
a[i]=b[i];
b[i]=tmp;
}
}

////////////////////////////////////////////////
// qsolve palautusarvo: //
// 1 <=> yhtälöryhmälle oli ratkaisu //
// 0 <=> yhtälöryhmälle ei ollut ratkaisua //
////////////////////////////////////////////////
int gsolve(lreal *X, lreal *f, int n)
{
lreal k, J;
lreal *max, *mux;
int i, j, x, M=(int)n+1;

for (i=0; i
{
max=f+i+i*M;
for (j=i+0x01; j < n; j++)
if (fabsl(*(mux=f+i+j*M))>fabsl(*max)) max=mux;

if (max!=(mux=f+i+i*M))
swapRows(max, mux, M-i);

if (fabsl(J=f[i+i*M])<(lreal)1e-20)
return 0; /* eipä ole ratkaisuva */

for (j=i+1; j
{
if (f[i+j*M])
{
k=-f[i+j*M]/J;
for (x=i+1; x
f[x+j*M]=f[x+j*M]+k*f[x+i*M];
}
}
}

for (i=n-1; i>=0; i--)
{
k=(lreal)f[n+i*M];
for (j=n-1; j > i; j--)
k=k-(lreal)(X[j]*f[j+i*M]);

if (fabsl(J=f[i+i*M])<(lreal)1e-20)
return 0; /* eipä ole ratkaisua */
else X[i]=k/J; /* onpa ratkaisu */
}

return 1;
}

real2d operator*(lreal k, real2d b)
{
real2d a(k);
return a*b;
}

real2d operator/(real2d a, lreal k)
{
real2d b(k);
return a/b;
}

real2d operator*(real2d a, lreal k)
{
real2d b(k);
return a*b;
}

real2d operator/(lreal k, real2d b)
{
real2d a(k);
return a/b;
}

real2d sqrt(real2d c)
{
if (ifpos(c))
{
real2d k(lr(0.5));
real2d x(lr(1.0));

for (int i=0; i<256; i++)
{
x=k*(x+c/x);
}
return x;
}
else
{
/* virhe, luku ei ole positiivinen */
return real2d(-(lreal)0xfedca201L);
}
}

void print(real2d a)
{
a = (real2d) reduse(a);
printf("(%0.21f, %0.21f)\n",
(double)a.e[0], (double)a.e[2]);
}

real2d pow(real2d x, int n)
{
if (n)
{
real2d t=x;
int i=n<0? -n: n;
for (--i; i; i--) t=t*x;
return n>0? t: real2d(1.0)/t;
}
else
{
return real2d(1.0);
}
}

real2d ln(real2d c)
{
int n=1;
lreal t;
real2d fx, dx;
real2d x1, x2;
real2d z(1.0);
real2d x(1.0), xx;
#define MAX 3.14159265e+36

if (!ifpos(c))
{
/* virhe, luku ei ole positiivinen */
return real2d(-(lreal)0xfedca201L);
}

while (abs(c)>lr(1.001))
{
c=sqrt(c);
n+=n;
}

for (int k=2; k<160; k++)
for (int j=0; j<160; j++)
{
xx=x; t=1.0;
fx=z+x; dx=z;

for (int i=2; i<=k; i++)
{
dx=dx+i*xx/(t*=i);
xx=xx*x; fx=fx+xx/t;
if (mgn(fx)>MAX) break;
}

x1=x;
x=x-(fx-c)/dx;
x2=x;

if (k+1 < 160)
{
if (mgn(x1-x2)<1e-15) break;
}
}

return (lreal)n*x;
}

real2d exp(real2d x)
{
real2d xx;
lreal t=1.0;
real2d sum(1.0);

sum=sum+(xx=x);

for (int i=2; i<160; i++)
{
xx = xx*x;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

real2d pow(real2d a, real2d x)
{
lreal t=1.0;
real2d sum(1.000);
real2d y=x*ln(a), xx=y;

sum=sum+xx;

for (int i=2; i<160; i++)
{
xx = xx*y;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

real2d pow(real2d x, lreal ex)
{
return pow(x, real2d(ex));
}

real2d sin(real2d x)
{
lreal t=1.0;
real2d sum(0.0);
real2d y=x*x, xx=x;

for (int i=1, sg=0; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

real2d cos(real2d x)
{
lreal t=2.0;
real2d sum(1.0);
real2d y=x*x, xx=y;

for (int i=2, sg=1; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

class complex2d
{
public:

real2d r, i, j, k;

complex2d(void);
complex2d(int);

complex2d(lreal);
complex2d(real2d);

complex2d(lreal, lreal);
complex2d(real2d re, real2d im);
complex2d(real2d, real2d, real2d, real2d);

friend lreal abs(complex2d);
friend void print(complex2d);
friend complex2d sqrt(complex2d);
friend complex2d operator-(complex2d);

friend complex2d operator+(complex2d, complex2d);
friend complex2d operator-(complex2d, complex2d);

friend complex2d operator*(complex2d, complex2d);
friend complex2d operator/(complex2d, complex2d);

friend complex2d operator*(lreal, complex2d);
friend complex2d operator/(complex2d, lreal);

friend complex2d operator*(complex2d, lreal);
friend complex2d operator/(lreal, complex2d);

/* mgn = luvun suuruus */
friend lreal mgn(real2d);
friend complex2d ln(complex2d);
friend complex2d exp(complex2d);
friend complex2d sin(complex2d);
friend complex2d cos(complex2d);
friend complex2d pow(complex2d, int);
friend complex2d pow(complex2d, lreal);
friend complex2d pow(complex2d, complex2d);
};

complex2d::complex2d(void)
{
r=i=j=k=real2d(0);
}

complex2d::complex2d(int a)
{
r=real2d(a, 0);
i=j=k=real2d(0);
}

complex2d::complex2d(lreal a)
{
r=real2d(a, 0.0);
i=j=k=real2d(0.0);
}

complex2d::complex2d(real2d a)
{
r=a; i=j=k=real2d(0);
}

complex2d::complex2d(lreal a, lreal b)
{
r=real2d(a, b);
i=j=k=real2d(0);
}

complex2d::complex2d(real2d a, real2d b)
{
r=a; i=b; j=k=real2d(0);
}

complex2d::complex2d(real2d a, real2d b, real2d c, real2d d)
{
r=a; i=b; j=c; k=d;
}

complex2d operator-(complex2d a)
{
return complex2d(-a.r, -a.i, -a.j, -a.k);
}

complex2d operator+(complex2d a, complex2d b)
{
return complex2d(a.r+b.r, a.i+b.i, a.j+b.j, a.k+b.k);
}

complex2d operator-(complex2d a, complex2d b)
{
return complex2d(a.r-b.r, a.i-b.i, a.j-b.j, a.k-b.k);
}

complex2d operator*(complex2d a, complex2d b)
{
complex2d c;

c.r = real2d(1,0,0,0)*a.r*b.r + real2d(0,1,0,0)*a.i*b.i
+ real2d(0,0,1,0)*a.j*b.j + real2d(0,0,0,1)*a.k*b.k;

c.i = real2d(1,0,0,0)*a.r*b.i + real2d(1,0,0,0)*a.i*b.r
+ real2d(1,0,0,0)*a.j*b.k + real2d(1,0,0,0)*a.k*b.j;

c.j = real2d(1,0,0,0)*a.r*b.j + real2d(0,0,0,1)*a.i*b.k
+ real2d(1,0,0,0)*a.j*b.r + real2d(0,0,0,1)*a.k*b.i;

c.k = real2d(1,0,0,0)*a.r*b.k + real2d(0,0,1,0)*a.i*b.j
+ real2d(0,0,1,0)*a.j*b.i + real2d(1,0,0,0)*a.k*b.r;

return c;
}

complex2d operator/(complex2d a, complex2d b)
{
complex2d L;
real2d z(0);

L=complex2d(b.r, b.i, -b.j, -b.k);
a = a*L;
b = b*L;

L=complex2d(b.r, -b.i, z, z);
a = a*L;
b = b*L;

a.r = a.r/b.r;
a.i = a.i/b.r;
a.j = a.j/b.r;
a.k = a.k/b.r;

return a;
}

complex2d operator*(lreal a, complex2d b)
{
return complex2d(a*b.r, a*b.i, a*b.j, a*b.k);
}

complex2d operator/(complex2d a, lreal b)
{
return complex2d(a.r/b, a.i/b, a.j/b, a.k/b);
}

complex2d operator*(complex2d a, lreal b)
{
return complex2d(b*a.r, b*a.i, b*a.j, b*a.k);
}

complex2d operator/(lreal a, complex2d b)
{
return complex2d(a)/b;
}

lreal mgn(complex2d a)
{
lreal sum=0;
sum+=mgn(a.r);
sum+=mgn(a.i);
sum+=mgn(a.j);
sum+=mgn(a.k);
return sum;
}

lreal abs(complex2d a)
{
complex2d L;
real2d z(0);

L=complex2d(a.r, a.i, -a.j, -a.k);
a = a*L;

L=complex2d(a.r, -a.i, z, z);
a = a*L;

a.r=pow(a.r, lr(0.25));

return abs(a.r);
}

complex2d sqrt(complex2d c)
{
if (mgn(c)<1e-20)
{
return complex2d(0);
}
else
{
complex2d x=c;
for (int i=0; i<160; i++)
x=x-(x*x-c)/(2.0*x);
return (complex2d)x;
}
}

complex2d sin(complex2d x)
{
lreal t=1.0;
complex2d sum(0.0);
complex2d y=x*x, xx=x;

for (int i=1, sg=0; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

complex2d cos(complex2d x)
{
lreal t=2.0;
complex2d sum(1.0);
complex2d y=x*x, xx=y;

for (int i=2, sg=1; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

complex2d pow(complex2d x, int n)
{
if (n)
{
complex2d t=x;
int i=n<0? -n: n;
for (--i; i; i--) t=t*x;
return n>0? t: complex2d(1.0)/t;
}
else
{
return complex2d(1.0);
}
}

complex2d ln(complex2d c)
{
int n=1;
lreal t;
complex2d fx, dx;
complex2d x1, x2;
complex2d z(1.0);
complex2d x(1.0), xx;

while (abs(c)>1.001)
{
c=sqrt(c);
n+=n;
}

for (int k=2; k<160; k++)
for (int j=0; j<160; j++)
{
xx=x; t=1.0;
fx=z+x; dx=z;

for (int i=2; i<=k; i++)
{
dx=dx+i*xx/(t*=i);
xx=xx*x; fx=fx+xx/t;
if (mgn(fx)>MAX) break;
}

x1=x;
x=x-(fx-c)/dx;
x2=x;

if (k+1 < 160)
{
if (mgn(x1-x2)<1e-15) break;
}
}

return (lreal)n*x;
}

complex2d exp(complex2d x)
{
complex2d xx;
lreal t=1.000;
complex2d sum(1);

sum=sum+(xx=x);

for (int i=2; i<160; i++)
{
xx = xx*x;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

complex2d pow(complex2d a, complex2d x)
{
lreal t=(lreal)1;
complex2d sum(1.000);
complex2d ln(complex2d);
complex2d y=x*ln(a), xx=y;

sum=sum+xx;

for (int i=2; i<160; i++)
{
xx = xx*y;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

complex2d pow(complex2d x, lreal n)
{
return pow(x, complex2d(n));
}

void print(complex2d a)
{
printf("[\n");
printf(" r="); print(a.r);
printf(" i="); print(a.i);
printf(" j="); print(a.j);
printf(" k="); print(a.k);
printf("]\n");
}

int main(void)
{
return 0;
}[/code:hdkwnpbo]

Uusimmat

Suosituimmat