Esercizo n3 Numero Primo



  • Esercizo n.3: Numero Primo
    di Luca73 data: 07/04/2015 09:24:40

    Ciao a tutti
    scusate il ritardo ma la Pasqua ha avuto il sopravvento.
    Inoltre ci ho dovuto pensare un po su per trovare qualcosa all'altezza di questo forum (anche se non so se ci sono riuscito).
    Ringrazio scossa per la nomina e colgo l'occasione per ringraziare ci ha inventato e chi gestisce questo forum nonché tutti colore che in ogni forma partecipano, grazie a voi ho imparato numerosi trucchetti e cose che non sapevo.
    Per Ninai: Ha i ragione nella formula c'era un errore che scossa ha prontamente corretto (un banale ma ingiustificabile copia incolla)

    Vi propongo questo quesito:

    dato un numero intero qualsiasi (assumerei incluso tra 1 e 1E8) definire se esso è un numero primo oppure no (dicesi numero primo un numero che può essere diviso senza resto solo per 1 e per sè stesso).
    Come formule Excel il requisito è minimizzare le celle di appoggio (in A1 il numero, il risultato deve essere un booleano: Vero/Falso, Vero= numero primo)
    Come Function in input il numero, in output un booleano (Vero/Falso; Vero= numero primo); obiettivo minimizzare i cicli.

    Spero non sia troppo banale.
    Lascio a Vecchio Frac e/o scossa ulteriori regole di partecpazione.
    Ciao Luca





  • di scossa data: 07/04/2015 12:13:29

    cit. Luca73: "assumerei incluso tra 1 e 1E8"

    se con 1E8 intendi 1*10^8, cioè 100.000.000 - così, d'istinto - mi sembra eccessivo, almeno per una soluzione lato formule, considerando che le righe di un foglio excel (dal 2007 ...) sono 1.048.576, per cui ti proporrei di rivedere al ribasso, ad esempio tra 1 e 1.000.000 o, per mantenere la compatibilità con il 2003, tra 1 e 65.000.

    Il mio è solo un suggerimento, quindi se vuoi lasciare il limite di 100.000.000 va bene così.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno.
    Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)



  • di ninai (utente non iscritto) data: 07/04/2015 12:39:48

    si deve aspettare??? oppure no????



  • di scossa data: 07/04/2015 12:44:02

    @ninai: direi che, come per l'altra volta, gli "utenti esperti", e tu ci sei dentro comunque , rispondano a partire da domani, altrimenti si rischia di tagliare le gambe agli altri .....


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno.
    Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)



  • di ninai (utente non iscritto) data: 08/04/2015 07:39:29

    la propongo adesso che oggi sono fuori:
    se i numeri sono fino a 100.000.000, si potrebbe usare:
    =MATR.SOMMA.PRODOTTO(--(RESTO(A1;RIF.RIGA($1:$10000))=0))=1+(A4<10000)
    in A1 in numero da verificare.
    dovrebbe funzionare ma confesso che non l'ho testata bene



  • di Mister_x (utente non iscritto) data: 08/04/2015 09:46:34

    ciao Ninai

    la tua formula lo testata pressapoco anch'io e direi che funziona
    ho apportato una modifica per il valore 1
    linconveniente sta che per la versione di excel 2003 e inferiore il limite di controllo e circa ad un valore max di 62000 perche le righe sono max 65536 mentre per 2007 e sup e' circa un 1000000 max dato che le righe in un foglio sono 1048576 quindi bisogna stare in questi parametri di controllo

    questo per 2003
    =SE(A1=1;VERO;MATR.SOMMA.PRODOTTO(--(RESTO(A1;RIF.RIGA($1:$65536))=0))=1+(A4<65536)) max controllo circa 62.000
    per 2007
    =SE(A1=1;VERO;MATR.SOMMA.PRODOTTO(--(RESTO(A1;RIF.RIGA($1:$1048576))=0))=1+(A4<1048576)) max controllo circa 1.000.000

    ciao
    per la mia versione in vb e in excel con colonne di appoggio aspetto ancora un pochino





  • di ninai (utente non iscritto) data: 08/04/2015 09:52:28

    Grazie per la correzione , mi ero accorto pure io del problema dell'1 e del refuso (A4) ma non riuscivo a connettermi, avevo preparato tale correzione:
    =MATR.SOMMA.PRODOTTO(--(RESTO(A1;RIF.RIGA($1:$10000))=0))=1+(A1<10000)*(A1>1)



  • di ninai (utente non iscritto) data: 08/04/2015 10:26:53

    Mister x
    10000 è la radice quadrata di 100000000 e fa funzionare la formula anche per numeri maggiori



  • di scossa data: 08/04/2015 11:44:34

    Bravo ninai! Ormai sei troppo forte.

    Io ci avevo provato a metterti (mettervi) fuori strada col mio post sul numero di righe massimo di excel, ma non ci sei cascato!



    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno.
    Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)




  • di Mister_x (utente non iscritto) data: 08/04/2015 12:28:35

    ciao ninai

    adesso mi sono accorto dove era l'errore
    stavo provando su unaltra colonna e non cambiavo il riferimento

    RESTO(F1;RIF.RIGA($1:$10000))=0))=1+(A4<10000)

    OK

    ciao





  • di Albatros54 (utente non iscritto) data: 08/04/2015 15:00:40

    Scusate, qualcuno puo spiegare i vari passaggi per giungere alla formula postata da ninai?






    -----------------------------------------------------------------------
    " Sono le persone che nessuno immagina che possano fare certe cose
    quelle che fanno cose che nessuno puo' immaginare"
    (Joan Clarke)



  • di Ninai (utente non iscritto) data: 08/04/2015 16:07:56

    Ci provo , sono con il tel. Si basa sul presupposto che un numero primo è divisibile per se stesso è per uno. Pertanto qualunque numero primo, dividendolo per un numero da 1 a 100000000 (rif.riga()), darà due volta resto zero. siccome le righe sono meno di cento milioni, ho usato la radice quadrata di 100 milioni che è 10000. perciò se il numero è minore di 1000 avrà 2 resto zero, se è maggiore, avrà solo un resto pari a zero. Eccezione fa l'uno che prevedo con l'ultima parte della formula


  • numero primo
    di canapone (utente non iscritto) data: 08/04/2015 16:37:02

    Ciao a tutti,

    seguo il ragionamento di Ninai (ciao), per ridurre i calcoli prodotti dal rif.riga forse potrebbe funzionare

    =SE(A1<2;VERO;SE(E(INDICE(RESTO(A1;RIF.RIGA(INDIRETTO("2:"&ARROTONDA.PER.ECC(RADQ(A1);0))))>0;));VERO;FALSO))

    Se 1 non lo voglio considerare numero primo

    =SE(A1=2;VERO;SE(E(INDICE(RESTO(A1;RIF.RIGA(INDIRETTO("2:"&ARROTONDA.PER.ECC(RADQ(A1);0))))>0;));VERO;FALSO))

    Credo che le formule possano essere sforbiciate un po'.

    Saluti



  • di ninai (utente non iscritto) data: 08/04/2015 21:28:54

    ciao a tutti
    sono rientrato e mi è toccato dare l'allerta a tutti i neuroni che mi sono rimasti, per capire (grosso modo) la formula di Canapone (riesci sempre a frastornarmi) .

    Mi ha dato pure lo spunto di rendere il range del rif.riga(1:10000) dinamico, in base al numero da analizzare:

    =MATR.SOMMA.PRODOTTO(--(RESTO(A1;RIF.RIGA(INDIRETTO("1:"&INT(A1^(1/2))+1)))=0))=1+(A11)

    Scossa
    grazie del riscontro positivo, ormai con te sto sempre allerta.



  • di ninai (utente non iscritto) data: 08/04/2015 21:34:26

    la formula è storpiata, metto spazi vuoti fra gli operatori < e > :

    =MATR.SOMMA.PRODOTTO(--(RESTO(A1;RIF.RIGA(INDIRETTO("1:"&INT(A1^(1/2))+1)))=0))=1+(A1 < INT(A1^(1/2))+1)*(A1 > 1)



  • di Mister_x (utente non iscritto) data: 08/04/2015 23:56:44

    ciao

    proposta di una funzione in VBA da inserire in un modulo di classe
    Utilizzo in A1 il tuo valore in altra cella
    =Nprimo(A1)

    con colonne di appoggio io ho creato nel foglio una tabella con tutti i numeri primi con la sub() che ho inserita dopo la function, questa va inserita nel foglio di utilizzo
    PS per funzionare necessita della funzione sopra sempre
    con il nostro dato in A1 in B1
    =SE(MATR.SOMMA.PRODOTTO(--(E$1:G$60000=A1))=1;VERO;FALSO)

    ciao


     
    Option Explicit
    Public Function Nprimo(ByVal Numero As Double) As Boolean
    ''Utilizzo   Nprimo( il numero intero da verificare)
    Application.Volatile
    Dim i As Long
        If Numero <> Fix(Numero) Then '' controllo se ci sono decimali inseriti
         Nprimo = False
         Exit Function
        End If
        If Numero < 1 Then  '' controllo per il valore 0
         Nprimo = False
         Exit Function
        End If
      For i = 2 To Sqr(Numero) + 1  ''radice quadrata del numero , Numero di cicli per calcolo Mod
        If Numero Mod i = 0 And Numero <> i Then  '' per numero primo nessuna corrispondenza
             Nprimo = False                       '' numero non primo Mod riporta 0
             Exit Function
        End If
      Next i
    Nprimo = True  '' e un numero primo
    End Function
      ''''''''''''''''''''
    Sub ScriveNprimi()
    Dim o As Long
    Dim Nrig As Long, Ncol As Long
    Nrig = 1
    Ncol = 5
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    For o = 1 To 1000000
     If Nprimo(o) = True Then
      Cells(Nrig, Ncol) = o
      Nrig = Nrig + 1
     End If
     If Nrig > 59999 Then
      Nrig = 1
      Ncol = Ncol + 1
     End If
    Next o
    Application.EnableEvents = True
    Application.ScreenUpdating = False
    End Sub
    






  • di Luca73 data: 10/04/2015 08:29:55

    Ciao a tutti
    da oggi e per tutta la settimana prossima sarò molto preso perciò avrò poco tempo da dedicare al forum.
    Chiedo gentilmente a scossa o Vecchio Frack se possono nominare il "vincitore".
    Io, come ruspante utilizzatore di excel avevo pansato ad usare un sistema iterativo con formule con riferimenti circolari ed un sistema di azzeramento del divisore.
    Pertanto ho scritto
    in A1 il mio numero
    in B2 =SE(A1<>D4;1;SE(E(C3;B2<=RADQ(A1));B2+1;B2))
    in C3 =SE(O(A1<>D4;A1=1;A1=2);VERO; SE(RESTO(A1;B2)=0;FALSO;VERO))
    in D4 =SE(A1<>D4;A1;D4)
    in C3 ottengo il mio risultato Vero/Falso
    Il programma VBA è sotto ripotato.
    Ciao a tutti Luca
     
    Function NumeroPrimo(MioRange As Range) As Variant
    Dim Divisore As Double
    If MioRange.Cells.Count > 1 Then
        NumeroPrimo = "Errore, Selezionate troppe celle"
    ElseIf ((MioRange.Value Mod 2) = 0) Then
        NumeroPrimo = False
    Else
        NumeroPrimo = True
        For Divisore = 3 To Int(Sqr(MioRange.Value)) Step 2
            If ((MioRange.Value Mod Divisore) = 0) Then
                NumeroPrimo = False
                Exit Function
            End If
        Next Divisore
    End If
    End Function






  • di Mister_x (utente non iscritto) data: 10/04/2015 10:03:06

    ciao

    ciao luca,
    per mia conoscenza alle proposte che vengono fatte , mi pace provare tutte le soluzioni che vengono portate a conoscenza, e ho visto che nella tua, guardandola cosi ad occhio, ho notato che non hai tenuto conto del valore 2 e dei valori immessi a con decimali
    infatti provandola nel mio file dove ho inserito le varie soluzioni ho riscontrato questo
    ho apportato delle modifiche per far si che questo non succeda
    PS bella la soluzione, che se per caso venga immesso un range di celle e non la singola cella al posto di errore venga riportato un messaggio
    posto la tua funzione con le modifiche che ho fatto

    ciao
     
    Function NumeroPrimo(MioRange As Range) As Variant
    Dim Divisore As Double
    If MioRange.Cells.Count > 1 Then
        NumeroPrimo = "Errore, Selezionate troppe celle"
    End If
    If MioRange.Value - Fix(MioRange.Value) <> 0 Then  ''controllo decimali
        NumeroPrimo = False
    ElseIf ((MioRange.Value Mod 2) = 0) And MioRange.Value <> 2 Then ''controllo pari e 2 Nprimo
        NumeroPrimo = False
    Else
        NumeroPrimo = True
        For Divisore = 3 To Int(Sqr(MioRange.Value)) Step 2
            If ((MioRange.Value Mod Divisore) = 0) Then
                NumeroPrimo = False
                Exit Function
            End If
        Next Divisore
    End If
    End Function
    






  • di Luca73 data: 10/04/2015 10:29:18

    Ciao Mister_x
    Grazie per le correzioni ed i suggerimenti, sempre ben graditi ed utili.
    Ho solo notato che hai chiso il primo if con un end if e poi riapri un secondoi if con altre condizioni.
    In questo caso andrebbe inserito un Exit Function all'interno del primo if oppure trasformare il secondo if come elseif in quanto nel caso di errore di range non singolo il programma entrerebbe nel socondo if ...
    Inoltre (ma qui siamo al puntiglio per il controllo decimali avrei scritto
    NumeroPrimo = "Errore, Numero non Intero"

    Ciao
    Grazie
    Luca





  • di scossa data: 10/04/2015 15:40:15

    Essendo in questo periodo Vecchio Frac assente dal forum, mi assumo l'incarico di nonmiare il vincitore:

    "Signore e Signori,
    è per me un onore nominare, con unanime consenso del sottoscritto, il Prof. ninai quale vincitore, per aver proposto una formula concisa e funzionante (i numeri primi appartengono - per definizione - all'insieme dei numeri interi maggiori di 1), e non essersi fatto sviare da subdoli inganni.
    A lui gli auguri per l'esercizio del suo nuovo, delicato e complesso incarico di proporre il nuovo esercizio
    "





    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno.
    Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)




  • di ninai (utente non iscritto) data: 10/04/2015 19:56:35

    In attesa di ricevere il cospicuo assegno che Scossa , in qualità di sponsor con portafoglio, ha messo in palio, rifletterò sul quesito da porre, al momento non ho la più pallida idea di cosa proporre.