Oppure

Loading
27/11/13 21:38
HeDo
Nessuno gli fa notare che le varie funzioni Scomponi* sono almeno O(n) ? con n la lunghezza del numero convertito in stringa? Sai che il metodo ToString non è affatto _gratis_?

E' proprio l'approccio che è sbagliato, serve un'impementazione molto più matematica e molto meno "traduco la teoria a parole poi dalle parole ottengo il codice".

Non so se mi sono spiegato, ma quel codice scala malissimo :)
aaa
27/11/13 22:16
Fharamir
Postato originariamente da HeDo:

Nessuno gli fa notare che le varie funzioni Scomponi* sono almeno O(n) ? con n la lunghezza del numero convertito in stringa? Sai che il metodo ToString non è affatto _gratis_?

E' proprio l'approccio che è sbagliato, serve un'impementazione molto più matematica e molto meno "traduco la teoria a parole poi dalle parole ottengo il codice".

Non so se mi sono spiegato, ma quel codice scala malissimo :)


Hai colto nel segno, è esattamente ciò che ho fatto, son passato dalla teoria al codice.
So benissimo che esistono metodi già studiati e testati molto più efficienti del mio, ma se avessi voluto usare un metodo già pronto non mi sarei messo a scrivere un programma che cercava numeri primi.

Il mio scopo era quello di provare se la teoria poteva essere trasformata in un codice efficiente (senza troppe nozioni matematiche) e la risposta è palesemente: No. (mi pare ovvio)

Premesso questo io ho comparato due codici: uno mio e uno preso su questo sito.
Ne ho visto il funzionamento, il codice e l'esecuzione e mi sono meravigliato della differenza di tempi.

Analizzando questi 2 codici ho notato le differenze che elencavo nel primo post.

Sono d'accordo che il mio codice contiene molte più "righe" dell'altro, ma (almeno credevo) che queste righe in più facessero risparmiare molte più iterazioni di quante non ne facesse nelle funzioni di "scomponi".

Alla luce delle vostre informazioni, farò altre prove.

@HeDo
ToString non è gratis, ovvio, ma è "pesante"? Ci sono metodi migliori per ricavare le singole cifre di un numero?
(non per forza per questo programma, parlo in generale)
Ultima modifica effettuata da Fharamir 27/11/13 22:18
aaa
27/11/13 23:38
HeDo
Postato originariamente da Fharamir:

Hai colto nel segno, è esattamente ciò che ho fatto, son passato dalla teoria al codice.
So benissimo che esistono metodi già studiati e testati molto più efficienti del mio, ma se avessi voluto usare un metodo già pronto non mi sarei messo a scrivere un programma che cercava numeri primi.

Il mio scopo era quello di provare se la teoria poteva essere trasformata in un codice efficiente (senza troppe nozioni matematiche) e la risposta è palesemente: No. (mi pare ovvio)

Premesso questo io ho comparato due codici: uno mio e uno preso su questo sito.
Ne ho visto il funzionamento, il codice e l'esecuzione e mi sono meravigliato della differenza di tempi.

Analizzando questi 2 codici ho notato le differenze che elencavo nel primo post.

Sono d'accordo che il mio codice contiene molte più "righe" dell'altro, ma (almeno credevo) che queste righe in più facessero risparmiare molte più iterazioni di quante non ne facesse nelle funzioni di "scomponi".



qui purtroppo ti manca un po di teoria, ci sono degli esami all'università che trattano di algoritmi e complessità nei quali si trattano tutti gli aspetti del problema.

giusto per farsi un'idea basta consultare wikipedia: en.wikipedia.org/wiki/…
Alla luce delle vostre informazioni, farò altre prove.

@HeDo
ToString non è gratis, ovvio, ma è "pesante"? Ci sono metodi migliori per ricavare le singole cifre di un numero?
(non per forza per questo programma, parlo in generale)


si ci sono, puoi andarci con qualche colpo di operatori bitwise, ma comunque non risolveresti il problema alla radice :)
aaa
28/11/13 1:20
pierotofy
Postato originariamente da HeDo:
ci sono degli esami all'università che trattano di algoritmi e complessità nei quali si trattano tutti gli aspetti del problema.


Oppure un bel libro sull'argomento... l'universita' non ti serve.
Il mio blog: piero.dev
28/11/13 8:41
Fharamir
Già, purtroppo l'università l'ho dovuta interrompere per lavoro (scienze informatiche)
quindi quello che so è quasi totalmente autodidatta.

Ho provato a rimuovere l'esecuzione di tutti gli "Scomponi" e l'esecuzione è leggermente più veloce
(mi aspettavo meglio effettivamente)

Poi ho provato ad eliminare la memorizzazione dei numeri primi trovati e a verificare i numeri direttamente con tutti i dispari (invece che solo con i numeri primi). Il risultato però è sconfortante, nessun miglioramento.

Attualmente il codice che ho eseguito è questo:
        static void Main(string[] args)
        {
            UInt64 num;
            Boolean P;
            UInt64 stop;
            UInt32 tot = 0;

            Console.WriteLine("Premi Invio per iniziare il controllo e ESC per interromperlo...");
            Console.ReadLine();

            StreamWriter SW = new StreamWriter("Primi.TXT");

            num = 3;

            SW.WriteLine(num);
            Console.WriteLine(num);

            DateTime Start = DateTime.Now;

            do
            {
                while (!Console.KeyAvailable)
                {
                    num += 2;

                    P = true;
                    stop = (Convert.ToUInt64(Math.Sqrt(num)));

                    for (UInt32 x = 3; x < stop; x += 2)
                    {
                        if ((num % x) == 0) { P = false; break; }
                    }

                    if (P)
                    {
                        Console.WriteLine(num);
                        SW.WriteLine(num);
                        tot++;
                    }
                }
            } while (Console.ReadKey(true).Key != ConsoleKey.Escape);

            DateTime Stop = DateTime.Now;
            TimeSpan ts = Stop - Start;

            SW.Close();
            Console.WriteLine("Processo interrotto. Numeri primi trovati: " + tot);
            Console.WriteLine("\nTempo trascorso: " + ts.Seconds + " secondi");
            Console.ReadKey();
        }


Mentre il codice con cui l'ho confrontato è questo: (di Daniele Raimondi)
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stddef.h>
#define  OFP "listaPrimi.txt"
#define N_INT 50000
unsigned long int rad;
unsigned long int i, n = 3;
FILE *ofp;

int main(int argc, char** argv)
{
	if (!(ofp = fopen(OFP, "a")))
		{
			printf("\nErrore nell'apertura di %s", OFP);
			exit(1);
		}
	printf("\nIndicare il numero di partenza: ");
	scanf("%d", &n);
	int j, d;
	time_t start = time(NULL), int1 = time(NULL), int2;
	rad = (int) sqrt((double) n);	
		for (i = 2, j = 0, d = 0; ; i++)
		{
			if (j >= N_INT)
			{
				j = 0;
				int2 = time(NULL);
				printf("\nTrovati %d numeri primi.", d);
				printf("\nTempo totale trascorso = %.0lf sec, media tot = %.2lf num/sec", difftime(int2, start), N_INT / difftime(int2, start));
				printf("\nTempo ultimi %d numeri = %.0lf sec, media = %.2lf num/sec\n", N_INT, difftime(int2, int1), N_INT / difftime(int2, int1));
				int1 = time(NULL);
			}
			if(!(n % i))
			{
				//printf(" non è primo.");
				i = 1;
				n++;
				rad = (int) sqrt((double) n);
				continue;
			}
			else if (i >= rad)
			{
				//printf("\n%d", n);
				fprintf(ofp, "\n%d", n);
				i = 1;
				n++;
				d++;
				j++;
				rad = (int) sqrt((double) n);
				continue;
			}
		}

	return 0;
}
Ultima modifica effettuata da Fharamir 28/11/13 8:57
aaa
28/11/13 9:09
Fharamir
Ok, piccolo aggiornamento.

Ho eliminato la stampa a video dei numeri trovati.
Ora il secondo codice è "solo" 4 volte più rapido del primo.
(ma ancora non mi spiego il perché;)
aaa
28/11/13 9:19
Ultimo

Anche stampare a video immediatamente il risultato ti porta via del tempo, oltre che salvare il risultato immediatamente, anche questo porta via del tempo, quindi dovresti memorizzare prima i dati in RAM :d
in una Lista.

Concordo sul fatto che i metodi matematici siano i più efficienti
If ok Then GOTO Avanza else GOTO Inizia

28/11/13 9:42
Fharamir
Ho eliminato qualsiasi operazione di visualizzazione o salvataggio e reintrodotto quello in memoria.
Anche così però il miglioramento è minimo... :S

Non riesco a capire cosa rallenta così il mio codice... potrebbe essere la condizione del while? :-?

            do
            {
                while (!Console.KeyAvailable)
                {
                    num += 2;

                    P = true;
                    stop = (Convert.ToUInt64(Math.Sqrt(num)));

                    for (UInt32 x = 3; x < stop; x += 2)
                    {
                        if ((num % x) == 0) { P = false; break; }
                    }

                    if (P)
                    {
                        Primi.Add(num);
                    }
                }
            } while (Console.ReadKey(true).Key != ConsoleKey.Escape);

            DateTime Stop = DateTime.Now;
            TimeSpan ts = Stop - Start;

            Console.WriteLine("Processo interrotto. Numeri primi trovati: " + Primi.Count());
            Console.WriteLine("\nTempo trascorso: " + ts.Seconds + " secondi");
            Console.WriteLine("\nPremi un tasto per visualizzare i numeri trovati e salvarli su file");
            Console.ReadKey();

            StreamWriter SW = new StreamWriter("Primi.TXT");
            foreach (UInt64 Pr in Primi)
            {
                SW.WriteLine(Pr);
                Console.WriteLine(Pr);
            }
            SW.Close();
            Console.WriteLine("\nSalvataggio completato.");
            Console.ReadKey();
aaa