Kann mir jemand das optimieren?

RyoOhki

Grünschnabel
Ich habe ein Programm geschrieben um Wurzeln auf beliebig viele Nachkommastellen ausrechnen zu lassen, leider hab ich das Problem, dass das Ganze ab ca 500000 Nachkommastellen unglaublich langsam wird.

Ich habe die meisten der Rechenaufgaben in kleine Funktionen gepackt und in eine DLL verfrachtet und mir tagelang den Kopf darüber zerbrochen wie ichs noch optimieren könnte, weis aber nicht mehr weiter.

Jetzt such ich jemanden mit mehr Ahnung, der vielleicht auch Lust hat die Funktionene (eigentlich alle sammt ziemlich klein, meistens nur eine Schleife und ein haufen Additionen und evt. Multiplikationen) zu optimieren oder in ASM neuzuschreiben.

Ich posteeinfach mal den Code der funktionen. Die übergebenen pointer sind immer pointer auf ein Array, wobei der letzte verwendete index des arrays immer in Index 0 vermerkt ist:

long *zahl wird z.B. übergaben,
in zahl[0] steht dann z.B. 10, wenn zahl1[10] das letzte (benutzte) index ist.
die den arrays sind die zahlen mit denen gerechnet wird gespeichert, wobei je ein index eine stelleder zahl ist:
1234567 würde z.B. in ein 8-stelliges array gespeichert, wobei array[0] dann 7 enthalten würde, weil das der letzte verwendete index ist.

PHP:
//Funktion subtrahiert die zahl im array zahl2 von array zahl1 ab
extern "C" long __declspec(dllexport) WINAPI LONG_SUB(long *zahl1, long *zahl2)
{        

    long l1 = zahl1[0];  //länge zahl1
    long l2;                    //länge zahl2
    long i;
    
        for (l2 = zahl2[0]; l2 >= 1; l2--)
        {
            if (zahl1[l1] < zahl2[l2])   //Wenn übertrag entsteht
            {
                zahl1[l1] = zahl1[l1] + 10 - zahl2[l2];

                l1--;
                i = l1;
                
                while (zahl1[i] == 0)
                {
                    zahl1[i] = 9;
                    i--;
                }

                zahl1[i]--;
            }
            else   //ohne übertrag
            { 
                   zahl1[l1] = zahl1[l1] - zahl2[l2];
                   l1--;
            }

        }
        
    return 0;
       
}


//Funktion addiert die zahl in array zahl2 zu array zahl1 
extern "C" long __declspec(dllexport) WINAPI LONG_ADD(long *zahl1, long *zahl2)
{

    long l1 = zahl1[0];  //länge zahl1
    long l2;                    //länge zahl2
    
      for (l2 = zahl2[0]; l2 >= 1; l2--)
      {   
        zahl1[l1] = zahl1[l1] + zahl2[l2];
        
        if (zahl1[l1] > 9)    //Falls übertrag entsteht
        {
            zahl1[l1] = zahl1[l1] - 10;
            l1--;
            zahl1[l1]++;      
        }
        else    //phne übertrag
        {
            l1--;
        }
      }

    return 0;

}



//Funktion vergleicht die zahlen in arrays zahl1 und zahl2 und gibt den wert1 
//zurück, wenn zahl1 größer, 2 wenn zahl2 größer und 3 wenn die zahlen 
//identisch  sind
extern "C" long __declspec(dllexport) WINAPI LONG_COMP(long *zahl1, long *zahl2)
{

    long i; 
    
    for (i = 0; i <= zahl1[0]; i++)
    {        
        if (zahl1[i] > zahl2[i])
        {
            return 1;
        }
        if (zahl2[i] > zahl1[i])
        {
            return 2;
        }
    }
    
    return 3;

}

//Funktion multipliziert eine überlange zahl im array zahl1 mit einem wert von 
//0 bis 9. Die Funktion braucht wohl die meiste rechenzeit, alleine schon weil ich 
//für jedeStelle von zahl1 ein modulo anwenden muss um ein 2stelligezahl in 
//zehner und einer aufzubrechen. Ich habe leider keinen anderen weg gefunden 
extern "C" long __declspec(dllexport) WINAPI LONG_Mult(long *zahl1, long zahl2, long *ergebniss)
{

    long lz1, lz2, cache, c;
    long uebertrag = 0;
    
    lz1 = zahl1[0];
    lz2 = ergebniss[0];

        
        while (lz1 >= 1)
        {

             cache = zahl1[lz1] * zahl2;
                
             c = cache - (cache % 10);
                                   
             ergebniss[lz2] = cache - c + uebertrag;
             uebertrag = 0;
        
             if (ergebniss[lz2] > 9)
             {
                     ergebniss[lz2] = ergebniss[lz2] - 10;
                     uebertrag = 1;
             }
        
             if (cache > 9)
             {       
                     c = c / 10;
                     uebertrag = uebertrag + c;
             }

             lz2--;
             lz1--;
    
        }
      
    if (uebertrag != 0)
    {
        ergebniss[lz2] = uebertrag;
    }
    
      
    return 0;
}
also wenn jemand zeit lust und Interesse hätte fände ich das supernett!

Grüße undDank im vorraus, Ryo

[edit mod=joki]PHP-Code Tags eingefügt[/edit]
 
Zuletzt bearbeitet von einem Moderator:
V

Vaethischist

Also ich hab nicht unbedingt Lust auf Codeoptimierung, aber 'ne Frage:

Wer braucht 'ne Wurzel mit mehr als 500000 Nachkommastellen?:confused: :confused: :confused:
 

canuzzi

Erfahrenes Mitglied
modulo

Die modulo Geschichten sind nicht so zeitaufwendig. Du solltest schauen ob du nicht ein paar if abfragen rausbekommst. Wenn ich zeit dieses wochenende habe mach ich mir mal gedanken.

Gerade Geschichten wie modulo etc sind sehr maschinennahe operationen. Eventuel sollte man sich ueberlegen das ganze als grosses bitfeld zu berechnen
... so nur ein paar erste gedanken und infos