Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » Rätselecke » 2. Sonntagsrästel

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 <
010
23.07.2002, 18:34 Uhr
~NemoEimi
Gast


Ups, das kam falsch an. Hier nochmal eine Version hoffentlich ohne Copy&Paste-Fehler:


C++:
#include <stdio.h>
#include <cstdlib>

unsigned int smallprimes[65535], quadrate[65535];

bool prime_p(unsigned int n) {
  for (unsigned int i = 1; quadrate[ i ] <= n; i++)
    if (n%smallprimes[ i ]==0) return(0);
  return(1);
  }

unsigned int isqrt(unsigned int n) {
  unsigned int a = n, b = n-1;
  while (b < a) {
    a = b; b = a + n/a >> 1;
    }
  return(b);
  }

unsigned int naechste_primzahl(unsigned int n) {
  unsigned int k = n + 2;
  while (!prime_p(k)) {
    k = k + 2;
    }
  return(k);
  }

void erzeuge_erste_primzahlen(unsigned int n) {
  unsigned int z = 2;
  for (unsigned int i = 5; i <= n; i = naechste_primzahl(i)) {
    smallprimes[z] = i; quadrate[z] = i*i; z = z + 1;
    }
  }

inline bool twin_test(unsigned int n) {
  unsigned int m = n + 2;
  for (register unsigned int i = 1; quadrate[i] <= m; i++) {
    if (n%smallprimes[ i ]==0) return(0);
    if (m%smallprimes[ i ]==0) return(0);
    }
  return(1);
  }

int main(unsigned int argc, char *argv[]) {
  smallprimes[1] = 3; quadrate[1] = 9;
  unsigned int a = atoi(argv[1]); unsigned int b = atoi(argv[2]);
  erzeuge_erste_primzahlen(isqrt(b)+1);
  a = a - a%6 + 5;
  for (unsigned int i = a; i <= b; i=i+6)
    if (twin_test(i)) printf("%d\n",i);
  return(0);
  }

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
23.07.2002, 21:11 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich befürchte, wir müssen unsere Tests normieren, weil ich deutlich andere Ergebnisse bekomme als Du. Ich habe Dein Programm nemo.cpp genannt und so compiliert:

Code:
g++ -onemo nemo.cpp


meines heisst virt.c:

Code:
gcc -ovirt virt.c


Da ich mit einem xterm arbeite habe ich die Ausgabe in eine Datei umgeleitet, weil sonst in die Meßergebnisse mit einfliesst, wie schnell der X Server ist, das wollen wir ja nicht messen. Sitze jetzt an einem etwas langsameren Rechner als eben:

Code:
joe@puella:~/tmp> time nemo 2000000 3000000 >out 2>&1

real    0m0.645s
[b]user    0m0.640s[/b]
sys     0m0.010s

joe@puella:~/tmp> time virt 2000000 3000000 >out 2>&1

real    0m0.629s
[b]user    0m0.630s[/b]
sys     0m0.000s


Für Vergleiche ziehe ich die User Time ran.
Obwohl ich die doppelte Mege Text in der Datei produziere, ist meines noch immer um 1.5% schneller.

Wie hast Du gemessen?

Edit: Ich glaube, die Geschwindigkeitsunterschiede lassen sich auf eine ganz einfache Sache zurueckfuehren: ich mache deutlich weniger Funktionsaufrufe. Wenn die auch bei Deiner Lösung wegfallen würden, dann wärs etwa gleich, denke ich, weil sich die Algorithmen wirklich nur noch marginal unterscheiden
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 23.07.2002 um 21:45 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
23.07.2002, 22:54 Uhr
NemoEimi




Wie hast Du gemessen?


Ich habe mein Programm twins.cpp genannt, Dein Programm virtwins.c und dann mein Programm mit g++ -O3 twins.cpp compiliert und Deines mit gcc -O3 virtwins.c. Danach habe ich jeweils über time programmname 2000000 3000000 > test.txt bzw. > test2.txt die Zeiten gemessen, und dabei folgende Ergebnisse bekommen:

Mein Programm :

real 0m0.401s
user 0m0.400s
sys 0m0.000s

Dein Programm

real 0m0.462s
user 0m0.460s
sys 0m0.000s

(Das ergibt nicht die vorher behaupteten zwanzig Prozent Unterschied, aber bei der Messung, auf die ich mich in jenem Posting bezogen habe, hatte ich mehr Hintergrundprozesse laufen und das mag die Messergebnisse beeinflusst haben).

Grüße,
NemoEimi

Dieser Post wurde am 23.07.2002 um 23:02 Uhr von NemoEimi editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
24.07.2002, 07:39 Uhr
virtual
Sexiest Bit alive
(Operator)


Wirklich krass. Wenn ich das mit -O3 compiliere, wird der Unterschied noch größer, allerdings wiederum zu meinen Gunsten. Stellt sich die Frage: sind unsere Computer parteiisch? Liegt vielleicht auch einfach am Prozessor. kA.
Wir bräuchten einen unparteiischen Computer.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
24.07.2002, 22:51 Uhr
virtual
Sexiest Bit alive
(Operator)


Da es noch keiner getan hat, hab ich mich mal um das etwas schwerere Rästel gekümmert. Ist etwas länglich, daher habe ich auf Fehlerbehandlung weitestgehend verzichtet:

C++:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define EINE_TRILLIONEN 1000ull*1000ull*1000ull*1000ull*1000ull*1000ull

static const char* szBis20[] =
{
    "null", "ein", "zwei", "drei", "vier",
    "fünf", "sechs", "sieben", "acht", "neun",
    "zehn", "elf", "zwölf", "dreizehn", "vierzehn",
    "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn"
};

static const char* szEiner[] =
{
    "", "ein", "zwei", "drei", "vier", "fünf",
    "sechs", "sieben", "acht", "neun"
};

static const char* szZehner[] =
{
    "", "", "zwanzig", "dreisig", "vierzig", "fünfizig",
    "sechzig", "siebzig", "achzig", "neunzig"
};


static const char* szTausender[] =
{
    "trillionen", "billiarde", "billionen",
    "milliarde", "millionen", "tausend", ""
};


static void
n2s100(
    char* s,
    unsigned long long n)
{
    int bHundert = 0;
    
    if (n>=100)
    {
        strcat(s, szEiner[n/100]);
        strcat(s, "hundert");
        n %= 100;
        bHundert = 1;
    }
    if (n>=20)
    {
        if (n%10)
        {
            strcat(s, szEiner[n%10]);
            strcat(s, "und");
        }
        strcat(s, szZehner[n/10]);
    }else if (n>0)
    {
        strcat(s, szBis20[n]);
    }else if (!bHundert)
    {
        strcat(s, "null");
    }
}

static void
n2s(
    char* s,
    unsigned long long n)
{
    unsigned long long llTausender;
    int j;
    
    if (0==n)
    {
        strcat(s, "null");
        return;
    }
    
    for(j=0, llTausender = EINE_TRILLIONEN;
        7>j && 0!=n;
        ++j, llTausender /= 1000ull)
    {
        unsigned long long llHunderter = n/llTausender;

        if (0 != llHunderter)
        {
            n2s100(s, llHunderter);
            if (1==llHunderter)
            {
                if (1000ull<llTausender)
                {
                    strcat(s, "e");
                }else if (1ull==llTausender)
                {
                    strcat(s, "s");
                }
            }
            
            strcat(s, szTausender[j]);
            if (1==llHunderter && j%2==1 && 1000ull<llTausender)
            {
                strcat(s, "n");
            }

            n %= llTausender;
        }
    }
}


static unsigned long long
s2n100(
    char* s)
{
    unsigned long long n = 0ull;
    char* p;
    int j;
    
    p = strstr(s, "hundert");
    if (NULL != p)
    {
        *p = 0;
        for(j=1; j<10; ++j)
            if (0==strcmp(szEiner[j], s))
            {
                n += 100*j;
                break;
            }
        s = p+7;
    }
    p = strstr(s, "und");
    if (NULL != p)
    {
        *p = 0;
        for(j=0; j<10; ++j)
        {
            if (0==strcmp(s, szEiner[j]))
            {
                n += j;
                s += strlen(szEiner[j]);
                break;
            }
        }
        s = p + 3;
        for(j=2; j<10; ++j)
        {
            if (0==strcmp(s, szZehner[j]))
            {
                n += 10*j;
                s += strlen(szZehner[j]);
                break;
            }
        }
    }else
    {
        for(j=2; j<10; ++j)
        {
            if (0==strcmp(s, szZehner[j]))
            {
                n += 10*j;
                s += strlen(szZehner[j]);
                break;
            }
        }
        for(j=19; j>=0; --j)
            if (0==strncmp(s, szBis20[j], strlen(szBis20[j])))
            {
                n += j;
                s += strlen(szBis20[j]);
                break;
            }
    }

    return n;
}

static unsigned long long
s2n(
    char* s)
{
    unsigned long long n = 0;
    unsigned long long h;
    unsigned long long llTausender = EINE_TRILLIONEN;
    char* p;
    
    int j;
    for(j=0; j<6; ++j, llTausender /=1000ull)
    {
        p = strstr(s, szTausender[j]);
        if (NULL != p)
        {
            *p = 0;
            h = s2n100(s);
            n += llTausender*h;
            s = p+strlen(szTausender[j]);
            if (1==h && j%2==1 && 1000ull<llTausender) s++;
        }
    }
    if (strlen(s)) n += s2n100(s);
    return n;
    
}

#define ITEMSIZE sizeof(long long)
void
encode(
    FILE* in,
    FILE* out)
{
    char s[2048];
    unsigned long long buffer[1024];
    unsigned len;
    unsigned j;
    
    while (0<(len=fread(buffer, 1, ITEMSIZE*1024, in)))
    {
         if (len<1024*ITEMSIZE)
        {
            memset((char*)buffer+len, 0, ITEMSIZE);
            len = ITEMSIZE*((len+ITEMSIZE-1)/ITEMSIZE);
        }
        len /= ITEMSIZE;
        for(j=0; j<len; ++j)
        {
            s[0] = 0;
            n2s(s, buffer[j]);
            fprintf(out, "%s\n", s);
        }
    }
}

void
decode(
    FILE* in,
    FILE* out)
{
    char s[2048];
    unsigned long long n;
    
    while (fgets(s, sizeof(s), in))
    {
        s[strlen(s)-1] = 0;
        n = s2n(s);
        fwrite(&n, sizeof(n), 1, out);
    }
}


int
main(
    int argc,
    char** argv)
{
    const char* filename;
    char* backup;
    char buffer[4096];
    unsigned len;
    int mode = 'e';
    FILE* in;
    FILE* out;

    switch(argc)
    {
    case 2:
        filename = argv[1];
        break;
    case 3:
        filename = argv[2];
        mode = 'd';
        break;
    default:
        fprintf(stderr,"*** ERROR: illegal command line\nusage: sonntag2 [-d] file\n");
        exit(EXIT_FAILURE);
        break;
    }

    backup = malloc(strlen(filename)+5);
    sprintf(backup, "%s.tmp", filename);
    in = fopen(filename, "rb");
    out = fopen(backup, "wb");
    while (0<(len=fread(buffer, 1, sizeof(buffer), in)))
        fwrite(buffer, len, 1, out);
    fclose(in);
    fclose(out);
    
    in = fopen(backup, mode=='e'? "rb":"r");
    out = fopen(filename, mode=='e'? "w": "wb");
    if (mode=='e')    
        encode(in, out);
    else
        decode(in, out);
    fclose(in);
    fclose(out);

    remove(backup);
    free(backup);
    
    return EXIT_SUCCESS;
}


Ich verspreche, das nächste Mal ein Rätsel zu suchen, was sich mit weniger Aufwand lösen läßt.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
25.07.2002, 10:11 Uhr
Christian
C/C++ Master
(Operator)


Hallo!

Du hast ja bei deiner Lösung den Typ long long verwendet. Ist das zulässig?

Grüße
--
Grüße, Christian
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
25.07.2002, 10:26 Uhr
virtual
Sexiest Bit alive
(Operator)


Ja, deshalb hab ichs ja auch in C geschrieben, denn "long long" ist im ANSI C Standard von 99 mit drin. Leider ist long long im C++ Standard jedoch nicht mit drin (siehe erstes Posts dieses Threads)
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 <     [ Rätselecke ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: