Szeretettel köszöntelek a A Csodálatos Világűr-és a Föld közösségi oldalán!
Csatlakozz te is közösségünkhöz és máris hozzáférhetsz és hozzászólhatsz a tartalmakhoz, beszélgethetsz a többiekkel, feltölthetsz, fórumozhatsz, blogolhatsz, stb.
Ezt találod a közösségünkben:
Üdvözlettel,
A Csodálatos Világűr-és a Föld vezetője
Amennyiben már tag vagy a Networkön, lépj be itt:
Szeretettel köszöntelek a A Csodálatos Világűr-és a Föld közösségi oldalán!
Csatlakozz te is közösségünkhöz és máris hozzáférhetsz és hozzászólhatsz a tartalmakhoz, beszélgethetsz a többiekkel, feltölthetsz, fórumozhatsz, blogolhatsz, stb.
Ezt találod a közösségünkben:
Üdvözlettel,
A Csodálatos Világűr-és a Föld vezetője
Amennyiben már tag vagy a Networkön, lépj be itt:
Szeretettel köszöntelek a A Csodálatos Világűr-és a Föld közösségi oldalán!
Csatlakozz te is közösségünkhöz és máris hozzáférhetsz és hozzászólhatsz a tartalmakhoz, beszélgethetsz a többiekkel, feltölthetsz, fórumozhatsz, blogolhatsz, stb.
Ezt találod a közösségünkben:
Üdvözlettel,
A Csodálatos Világűr-és a Föld vezetője
Amennyiben már tag vagy a Networkön, lépj be itt:
Szeretettel köszöntelek a A Csodálatos Világűr-és a Föld közösségi oldalán!
Csatlakozz te is közösségünkhöz és máris hozzáférhetsz és hozzászólhatsz a tartalmakhoz, beszélgethetsz a többiekkel, feltölthetsz, fórumozhatsz, blogolhatsz, stb.
Ezt találod a közösségünkben:
Üdvözlettel,
A Csodálatos Világűr-és a Föld vezetője
Amennyiben már tag vagy a Networkön, lépj be itt:
Kis türelmet...
Bejelentkezés
A Középkor végén a csillagászatban Kopernikusz, Galilei és Kepler munkássága nemcsak minőségi fordulatot hozott (a Heliocentrikus Világkép megmondja, mi mi körül kering a Naprendszerben), hanem a csillagászoknak sikerült meghatározni a bolygópályák méretét is. Ha csak egy pillantást vetünk egy ide vonatkozó táblázatra láthatjuk, hogy a bolygópályák méretének eloszlása nem véletlenszerű, hanem valamilyen törvényszerűséget mutat. (Minél távolabb vagyunk a Naptól, annál nagyobb a (közel köralakú) bolygópályák közötti távolság.) Titius (1729-1796) alkotott egy számsorozatot, amely "ráhúzható" volt az ismert bolygók pályaméreteire. Ezt a számsorozatot Bode (1747-1826) zárt képletbe foglalta, és azóta a csillagászatban ez a számsor "Titius-Bode szabály" néven ismeretes. A témának hatalmas irodalma van (a NET-en is elérhető), leírják, hogy az Uránuszt 1781-ben (és a Cerest 1801-ben) "azon a helyen" (a Naptól olyan távolságra) találták meg, ahová a Titius-Bode szabály megjósolta őket, de az 1846-ban felfedezett Neptunuszra már nem érvényes. Továbbiakban a matematikai háttér ismertetése után kisérletet teszünk a számsorozat gépi előállítására elősször magas szintű programnyelven, majd gépi kódban.
1.) Vegyük a következő számsorozatot, ahol (az első kettőt kivéve) mindegyik szám kétszerese az előzőnek:
0 3 6 12 24 48 96 192 384
Adjunk hozzá mindegyik számhoz 4-et:
4 7 10 16 28 52 100 196 388
Ezt a számsorozatot izlés szerint még el lehet osztani 10-zel, de így jelen formájában - jó közelítéssel - megadja a bolygók Naptól mért középtávolságát az AU (Csillagászati Egység) tizedében mérve, bár tegyük hozzá, a legbelső bolygó (Merkúr) és a legkülső (Neptunusz) esetében nem ad pontos értéket, csak akkor, ha manipuláljuk a képletet (ami a Merkúr esetében meg is történik). (Az első számsorozatnak nem 0-val, hanem 1,5-tel kellene kezdődnie, az alábbi táblázatban "n" első értékének nem "mínusz végtelen"-nek, hanem mínusz 1-nek kellene lennie. Ha következetesek akarunk lenni, a Merkúrra mindkét esetben 5,5-et kapunk, ami jelentősen eltér a tényleges értéktől.)
2.) Vegyük a következő matematikai formulát: a(n) = 4 + 3×2^n.
Ezzel a képlettel számítsuk ki az alábbi táblázatot, ahol a kitevők (az első kettőt kivéve) számtani sorozatot alkotnak:
bolygó n a(n) tényleges
______________________________
Merkúr - végtelen 4 3,9
Vénusz 0 7 7,2
Föld 1 10 10
Mars 2 16 15,2
(Aszteroidák) 3 28 27,2
Jupiter 4 52 52,0
Szaturnusz 5 100 95,4
Uránusz 6 196 191,8
Neptunusz 7 388 300,6
(A táblázatban a Titius-Bode szabállyal nyert érték mellett feltüntettük a tényleges értéket is.)
3.) Legyen a(0) a Merkúr pálya mérete, a(1) pedig a Vénuszé. Ekkor a Földpálya méretét megkapjuk, ha Vénusz pályáját megszorozzuk 2-vel, majd a Merkúr pályáját kivonjuk belőle:
a(2) = 2*a(1)-a(0),
a Mars pályáját megkapjuk, ha a földpálya kétszereséből kivonjuk a Merkúrét:
a(3) = 2*a(2)-a(0),
általános esetben
a(n) = 2*a(n-1)-a(0),
azaz valamely bolygó Naptól mért középtávolságát megkapjuk, ha a sorrendben megelőző bolygó Naptól mért középtávolságának kétszereséből kivonjuk a merkúrpálya méretét. Ez a képlet (Dobó Andor-féle rekurzív formula) azonos eredményre vezet, mint az előző két pont. Ez utóbbi érdekessége, hogy tetszés szerinti mértékegységben dolgozhatunk vele, akár csillagászati egységben, akár kilométerben, akár mérföldben.
Fenti módszerek bármelyikét válasszuk is, a számítási munka annyira egyszerű, hogy fejben vagy papír-ceruza módszerrel is hamar célhoz érünk. Mégis, mivel a számítástechnika korát éljük, tűzzük ki célul, hogy programot írjunk a Titius-Bode szabály értékeinek kiszámítására. Ha az első algoritmust választjuk, a programlista ("Turbo C" nyelven) a következő képpen néz ki (a program AU-ban számol, élve a lebegőpontos aritmetika lehetőségeivel, a földpálya mérete egységnyi).
#include <stdio.h>
#include <math.h>
main ()
{
static *boly[] =
{"Mercury","Venus","Earth","Mars","(Asteroids)",
"Jupiter", "Saturn","Uranus","Neptune"};
int i; double a[9] ,d;
a[0] = 0.4;
d=0.3;
for (i=1; i<9; i++) {
a[i] = d+0.4;
d=2.0*d;
}
for (i=0; i<9; i++)
printf("%s %5.1lf\n",boly[i],a[i]);
}
Mint látható, a d változó 0.3-as értékkel indul, és minden ciklusban szorzódik 2-vel, ehhez már csak 0.4-et kell hozzáadni, és megkaptuk a soron következő értéket.
Rátérve az a(n) = 0.4 + 0.3×2^n képlet alkalmazására mindjárt megmutatjuk, hogyan nem szabad programozni, hogyan nem szabad megközelíteni egy problémát. (A program elejét és a második "for"-ciklust elhagytuk, mert egyezik az előzővel.)
int i; double a[9];
a[0] = 0.4;
for (i=1; i<9; i++)
a[i] = 0.4+0.3*pow(2.0,i-1);
Látszólag minden rendben van, matematikailag teljesen korrekt. Ugyanakkor programozástechnikai szempontból iszonyú árat fizettünk a pow(X,y) függvény használatáért, amellyel a 2-es szám soron következő hatványát kiszámítjuk. Az "X^y" kiszámítása ugyanis az X^y = exp(y*log(X)) azonosság alkalmazásával történik, azaz tartalmaz egy logaritmus-számítást, egy szorzást és egy exponenciális függvényt. Ezért a hatványozás művelete akár lebegőpontos aritmetikáról van szó, akár matematikai co-processzorral van dolgunk, a leglassabb művelet, ami csak létezik (ezért tartott az 1970-es évek első zsebszámológépein a hatványozás művelete több másodpercig). Célszerű tehát az alábbiak szerint egy újabb változó bevezetésével módosítani rövid programunkat.
int i,d; double a[9];
a[0] = 0.4;
d=1;
for (i=1; i<9; i++) {
a[i] = 0.4+0.3*d;
d=2*d; }
A helyzet sokat javult, bár még mindig van egy szorzás művelet többletünk, amiből az következik, hogy a legelső változat futási ideje rövidebb, mint az utóbbié, amelyben a Titus-Bode szabály zárt alakját vittük gépre.
Összefoglalva a tanulságokat elmondható, ha több cikluson át végzünk számításokat egy újabb ciklus elején ne kezdjünk mindent elölről, használjuk fel az előző ciklusban kapott részeredményeket. Esetünkben 2 soron következő hatványának kiszámítása kiváltható volt azzal, hogy az előző ciklusban kapott hatványmennyiséget megszoroztuk 2-vel.
Végére maradt a Dobó Andor-féle rekurzív formula programozása. Ebben az esetben nincs szükségünk a "d" változóra, de ez ma már nem erény, a mai modern számítógépeken annyi változót deklarálhatunk, amennyi jólesik, a memória gyakorlatilag végtelen. Futásidő szempontjából az utóbbi esetben - csakúgy, mint az elsőben - a cikluson belül egy szorzás és egy (az összeadás helyetti) kivonás áll. Mivel azonban egy egydimenziós tömb (vektor) elemei között végzünk műveleteket ez az utóbbi megoldás lassab az elsőnél, a tömb elemeinek címzése ugyanis (láthatatlanul) egy szorzást foglal magába (az indexet, "i"-t szorozni kell a tipus hosszával, ami double változóknál 8 Byte). A program törzse:
int i; double a[9];
a[0] = 0.4;
a[1] = 0.7;
for (i=2; i<9; i++)
a[i] = 2.0*a[i-1] - a[0];
Ha tovább akarunk javítani a futásidőn, érdemes kirándulást tenni az Assembly programozás világába. Egyszerű problémák esetén a futásidő (és a programkód hossza) jóval rövidebb lehet, mint a magas szintű nyelvek (PASCAL, C, stb.) esetében. Gépi kódú programozásban közvetlenül előírhatjuk, mi történjen a mikroprocesszor 16 bites regisztereivel. A "MOV AX,DX" művelet például azt eredményezi, hogy a DX regiszter tartalma átmásolódik az AX regiszterbe, az "ADD AX,DX" a két regiszter összegét állítja elő AX-ben, miközben DX tartalma változatlan marad. A Titius-Bode szabály első alakja Assemblyben így néz ki:
ORG 100H ; Origin of the "COM" program
START: LEA BX,MEZO ; Base
MOV CX,8 ; Counter
MOV DX,3 ; Data register
MOV AX,4 ; Accumulator
MOV [BX],AX ; Store Mercury
HUROK: ADD AX,DX ; Add
INC BX ; Increment pointer, 2×
INC BX
MOV [BX],AX ; Store data
SAL DX,1 ; *2
MOV AX,4 ; Constant
LOOP HUROK ; Decrement CX, go to "HUROK" if not zero
INT 20H ; Return to DOS or Windows
MEZO: END
Feltűnhet, hogy a programlista nem tartalmaz szorzó utasítást, holott az első C-programban a "d" változó értéke minden ciklusban szorzódik 2-vel. Ennek az a magyarázata, hogy a számítógép kettes számrendszerben ábrázolja a számokat, és így végez műveleteket rajtuk. A 10-es számrendszerben a 10-zel való szorzás úgy történik, hogy az eredeti számhoz hozzá írunk egy 0-t. Hasonlóan a 2-es számrendszerben a kettővel (a számrendszer alapszámával) való szorzás megoldható úgy, hogy a számot tartalmazó regiszter minden bitjét eggyel balra léptetjük (a legalsó bit 0 értéket vesz fel). A SAL utasítás (Shift Arithmetic Left) annyit léptet balra, amennyi a regiszter neve mögött áll, "SAL DX,1" esetében 1-et. Hely hiányában (az Assembly programot felülről lefelé írják, mint a kínai hieroglifákat) nem közöljük a program második részét, azt a ciklust, amely a kiszámított értékek kijelzését végzi. Szívesen fogadom az erre születő megoldásokat (a tizenhat bites adatokat át is kell konvertálni 10-es számrendszerbe).
A másik két megoldás ("Comment"-ek nélkül):
ORG 100H ORG 100H
START: LEA BX,MEZO START: LEA BX, MEZO
MOV CX,8 MOV CX,8
MOV DX,1 MOV DX,4
MOV AX,4 MOV AX,DX
MOV [BX],AX MOV [BX],AX
HUROK: MOV AX,3 MOV AX,7
PUSH DX HUROK: INC BX
MUL DX INC BX
ADD AX,4 MOV [BX],AX
INC BX SAL AX,1
INC BX SUB AX,DX
MOV [BX],AX LOOP HUROK
POP DX INT 20H
SAL DX,1 MEZO: END
LOOP HUROK
INT 20H
MEZO: END
A második esetben (bal oldali programlista) feltűnhet, hogy szerepel egy "MUL" (Multiply) utasítás is. Ebben az esetben már valódi szorzással állunk szemben, a mai mikroprocesszorok már képesek szorozni is. Ugyanakkor a szorzás művelete lenullázza az egyik operandust tartalmazó regisztert, esetünkben DX-et. Ezért a szorzás művelete előtt egy "PUSH" utasítással el kell menteni a zsákmemóriába (a "Stack"-be) DX tartalmát, majd később egy "POP"-pal ki kell olvasni onnan. Mint látható, a második megoldás kódja a 3 közül a leghosszabb, futásideje a legnagyobb, szemben a harmadik, utolsó változattal, mely a legrövidebb és a leggyorsabb. Utóbbi szépsége abban áll, hogy a cikluson belül két gépi kódú utasítással (egy balra léptetéssel és egy kivonással) sikerült előállítani a Naprendszer legfontosabb állandóit (a többi utasítás csak adminisztrál). A programnak "output"-ja nincs (helyesebben nem közöljük), a kiszámított értékeket csak sorban leteszi a számítógép memóriájába (további feldolgozásra várva). Így ebben a formájában (a kezdő "ORG" és a befejező "END" direktívákat nem számítva) a maga 13 Assembly utasításával (gépi kódra lefordítva 29 Byte) tudomásom szerint ez a világ legrövidebb csillagászati szoftvere (ami azért csinál valamit). A szerző ezzel szeretne bekerülni a Rekordok Könyvébe.
|
|
E-mail: ugyfelszolgalat@network.hu
Kommentáld!