Dovresti cambiare così l'ultimo passaggio altrimenti scrive anche 1:
For j = 1 To limite
If serie[j] > 1 Then ListaNumeri.Add(Str$(serie[j])) 'scrive i numeri primi rimasti nella Listbox
Next
:ciao:
All'interno del suo programma Top Fuel giustamente avverte che "sui numeri grossi (sopra il milione) il programma ci metterà parecchio".
Confrontiamo, dunque, per mera curiosità le prestazioni di Gambas con quelle di un codice scritto in C, trasformato in libreria dinamica .so richiamata successivamente in un programma Gambas.
Utilizzate un valore, ad esempio, di 10000000 (diecimilioni) per entrambe le prove - con il codice Gambas (quello già disponibile di Top Fuel) e con il codice C della libreria esterna .so - e verificate il tempo impiegato da ciascuno dei due programmi nel rispettivo processo dei dati.
Il programma Gambas che utilizzerà il codice C puro, sarà il seguente:
Private Extern Eratostene_C(limes As Integer) As Integer In "/tmp/crivello"
Public Sub Main()
Dim limite, i As Integer
limite = 10000000
' Crea l'apposita libreria dinamica .so esterna:
Creaso()
' Invoca la funzione esterna della libreria dinamica .so:
i = Eratostene_C(limite)
If i < 0 Then Error.Raise("Memoria insufficiente !")
End
Private Procedure Creaso()
File.Save("/tmp/crivello.c", "#include <stdio.h>\n"
"#include <stdlib.h>\n" &
"#include <string.h>\n" &
"#include <math.h>\n\n" &
"int Eratostene_C(int limes) {\n\n" &
" int lim, dim, i, j, z;\n" &
" int *list;" &
"\n\n" &
" dim = (limes / 2 + 1);\n" &
" if((list = (int *)calloc(sizeof(int), dim)) == NULL)\n" &
" return -1;\n\n" &
" for(i=0; i<dim; i++)\n" &
" list[i]=0;\n\n" &
" printf(\"2 \");\n\n" &
" lim = (int)sqrt(limes);\n\n" &
" for(j=1,i=3; i<=lim; ++j,i+=2) {\n" &
" if(!list[j]) {\n" &
" for(z=j+i; z<dim; z+=i)\n" &
" list[z] = -1;\n" &
" printf(\"%d \", i);\n" &
" }\n }\n\n" &
" for(; i<limes; i+=2, ++j)\n" &
" if(!list[j])\n" &
" printf(\"%d \", i);\n\n" &
" return 0;\n\n}")
Shell "gcc -o /tmp/crivello.so /tmp/crivello.c -shared -fPIC -lm" Wait
End
:-X
Il mio programma era solo un piccolo esercizio, buono a scopo didattico volendo, dopo aver trovato per caso su Wikipedia questa cosa del crivello di Eratostene. :)
Se poi è venuta fuori una base di confronto e magari di miglioramento, ben venga la cosa.
Prova a parlarne sulla Mailing List, sentiamo che ti dicono. :)
Giusto quello che dice vuott, ma si può anche discutere e provare a vedere come mai Gambas esaurisce la memoria a 600 milioni.
Sul mio computer ad esempio il codice di Top Fuel la esaurisce a 300 sempre milioni.
Lascio volentieri indagare Top Fuel sul suo codice. :P :P
Io mi sono spremuto per farlo diversamente (prendendo spunto da un articolo su internet) e pur avendo partorito il codice meno veloce (risultati su 100 milioni):
Vuott 22550,8399009705 msec / 22620,2738285065 msec
Top Fuel 36794,9628829956 msec / 36589,7300243378 msec
Gianluigi 41717,2560691833 msec / 41830,934047699 msec
sono arrivato a 2 miliardi (su 3 mi da out of bound e non memoria esaurita) anche se nell'attesa del risultato ho schiacciato un sonnellino ;D
Allego Codice foto documentale
Nota: Se non erro il codice di Vuott non fa uso di vettori e questo potrebbe spiegare il fatto che è veloce il doppio.
' Gambas module file
Fast
Public Sub Main()
Setaccio(100000000)
End
Private Sub Setaccio(n As Long)
Dim v As New Boolean[n + 1]
Dim l, j, i As Long
Dim StartTime As Float
Dim DiffTime As Float
StartTime = Timer
l = Int(Sqr(n) + 1)
For i = 2 To l
For j = i * i To n Step i
v[j] = True
Next
Next
For i = 2 To n
If v[i] = False Then
Print i
Endif
Next
DiffTime = Timer - StartTime
Print "Setaccio ", DiffTime * 1000; " msec"
End
:ciao: :ciao: :ciao:
Nel mio codice quello che rallenta tanto è il secondo loop, la prima parte individua i numeri non primi mettendoli a True in 7/8 secondi, tutto il resto se lo posta via questo:
For i = 2 To n
If v[i] = False Then
Print i
Endif
Next
Purtroppo io non conosco il C, tu non potresti tradurre in gambese il codice scritto in C per vedere se funziona meglio :D
:ciao: :ciao:
PS Chissà Top Fuel cosa voleva dire...
...potresti tradurre in gambese il codice scritto in C ....
...gambese ? ???
http://www.jokisaari.net/gambia/pics/gambia-map.gif
Ad ogni modo ecco la traduzione:
Public Sub Main()
Dim limite, dime, lim, i, j, z As Integer
Dim lista As Integer[]
limite = 1000000
dime = limite / 2 + 1
lista = New Integer[dime]
Print 2
lim = Sqr(CFloat(limite))
j = 1
i = 3
While i <= lim
If lista[j] = 0 Then
z = j + i
While z < dime
lista[z] = -1
z += i
Wend
Print i
Endif
i += 2
Inc j
Wend
While i < limite - 1
If Not lista[j] Then Print i
i += 2
Inc j
Wend
End
...gambese ? ???
http://www.jokisaari.net/gambia/pics/gambia-map.gif
:P :P :P
Ho notato che anche la console rallenta, infatti nel codice C si ottiene il result a seguire, pertanto se noi inseriamo dietro a Print nei codici in gambase :P la virgola (il doppio punto e virgola è più lento) riduciamo il gap col C, questi i risultati su 100 milioni nel mio computer:
Crivello in C vuott 22371,8590736389 msec / 22567,2857761383 msec
Setaccio Vuott 24636,3999843597 msec / 24362,3239994049 msec
Setaccio Top Fuel 26364,4378185272 msec / 25966,2098884583 msec
Setaccio Gianluigi 30971,825838089 msec / 29990,3969764709 msec
Il nuovo codice su 2 miliardi mi da memoria terminata.
:ciao: :ciao: :ciao: