Hier sollen kleine, effiziente Algorithmen der Numerik vorgestellt werden. Sollten Fehler in meinen Programmen entdeckt werden, so bitte ich diese mir unter meiner eMail-Adresse: andreas{dot}romeyke[at]web{dot}de zuzumailen. Ich bin auch an weiteren Algorithmen interessiert.
Die beschriebenen Programme können frei verwendet werden, Eine Kennzeichnung der Quelle wäre wünschenswert.
unsigned int egypt_mult (unsigned int a, unsigned int b) {
unsigned int tmp=0;
if ((a==0) || (b==0)) return (0);
do {
if ((a & 1)==1) /* Wenn a ungerade */
tmp=tmp+b;
b=b<<1; /* b=b*2 */
a=a>>1; /* a=a/2 */
} while (a>0); /* Wiederhole solange a>0 */
return (tmp);
}
Das Beispiel mit Integern ist hier langsamer als eine normale Multiplikation "a*b", das liegt an den Tests in der Schleife. Eine Optimierungsmöglichkeit, die bei großen Zahlen wirksam ist, ist zu prüfen, ob a>b, um dann a mit b zu tauschen, da ein kleineres a eher 0 wird.
unsigned int legendre_pow (unsigned int a, unsigned int b) {
unsigned int tmp=1;
if ((a==0)||(b==0)) return (1); /* je nach mathematischer Auffassung */
do {
if ((b & 1)==1) /* Wenn b ungerade */
tmp=tmp*a;
a=a*a;
b=b>>1; /* b=b/2 */
} while (b>0); /* Wiederhole solange b>0 */
return (tmp);
}
Diese Methode ist deutlich schneller als die Nutzung der auf den Datentyp double angepassten pow() Funktion der math.h. Sie ist auch deutlich schneller, als wenn man in einer Schleife a b-mal miteinander multipliziert. Auch hier gilt, der Effekt wird größer, je größer die Zahlen werden
unsigned float herons_squareroot (unsigned float a) {
unsigned float tmpx=1;
unsigned float tmpy;
if (a==0) return (0);
for (;;) {
tmpy=(tmpx+a/tmpx)/2;
if (abs(tmpx-tmpy)<0.00000000001f) /* gewuenschte Genauigkeit */
break;
tmpx=tmpy;
}
return(tmpx);
}
unsigned int euklids_ggt (unsigned int a, unsigned int b) {
int tmp;
if ((a==0)||(b==0)) return (0);
do {
if (a<b) { /* vertausche a,b */
tmp=a;
a=b;
b=tmp;
}
tmp=a-b;
a=b;
b=tmp;
} while (tmp>0); /* Wiederhole solange tmp>0 */
return (a);
}
unsigned float ta_ka_pi(unsigned float &a, unsigned float &b, unsigned float &c) {
unsigned float y=a;
unsigned float x=1;
a=(a+b)/2;
b=sqrt(b*y);
c=c-x*(a-y)*(a-y);
x=2*x;
};
Wobei die Funktion je nach gewünschter Genauigkeit wiederholt aufgerufen wird. Der Startaufruf lautet:
...
a=1;
b=1/sqrt(2);
c=0.25f;
for (...) {
ta_ka_pi(a, b, c);
}
pi=((a+b)*(a+b))/(4*c);
...
Was noch kommt? Mal sehen, ich werde demnächst noch schnelle Berechnung von Logarithmen vorstellen. Wer noch Ideen hat, was hier noch unbedingt reingehört, immer her damit!