+ Rispondi al Thread
Visualizzazione dei risultati da 1 a 6 su 6

Discussione: cicli e virgola mobile

  1. #1
    Marius44 non è in linea Scolaretto
    Luogo
    Catania
    Post
    312

    cicli e virgola mobile

    Buona sera a tutti
    Qualche tempo fa mi è capitata una cosa strana. Avevo necessità che venissero scritte sul Foglio delle cifre in sequenza distanziate di un centesimo. Ho impostato questa macro
    codice:
    'Option Explicit
    
    Sub Elenca()
    'Dim i As Single, j As Single, a As Long
    Range("A:B").ClearContents
    For i = 0 To 1.3 Step 0.1
      a = a + 1
      Cells(a, 1) = i
    Next i
    
    a = 0
    For j = 0 To 1.4 Step 0.1
      a = a + 1
      Cells(a, 2) = j
    Next j
    End Sub
    Come noterete ho messo gli apici davanti a Option Explicit e alle dichiarazioni delle variabili.
    Se lanciate la macro così come è vedrete che in col.A vengono elencati tutti i valori fino al limite superiore compreso mentre in col.B il limite superiore non viene scritto.
    Se, invece, lanciate la macro eliminando gli apici più sopra detti, vedrete che in entrambe le colonne i valori si fermano prima del limite superiore di ciascun ciclo.

    Perchè?
    Mi sono data la spiegazione che (come è noto) Excel nel calcoli in virgola mobile utilizza 15 decimali e da qui nasce l'apparente incongruenza.

    Ma come si può ottenere la scrittura del limite superiore?

    Ovvio che ho trovato la soluzione (anzi due). Provate anche voi e date le vostre soluzioni.
    Domenica posterò quelle mie (se non le avete trovate prima voi).

    Ciao e buon divertimento con Excel-VBA,
    Mario

  2. #2
    L'avatar di Max.Riservo
    Max.Riservo non è in linea Scribacchino
    Post
    596
    Quote Originariamente inviato da Marius44 Visualizza il messaggio
    codice:
    ...
    For i = 0 To 1.3 Step 0.1
      a = a + 1
      Cells(a, 1) = i
    Next i
    Lascia perdere i decimale nel ciclo for/next ma calcolali direttamente nell'assegnazione del valore :

    codice:
    Dim i as integer, a as integer
    
    a = 0 'da inizializzare al valore di partenza che ti serve
    
    For i = 0 To 13
      Cells(a + i, 1) = i / 10
    Next i
    I calcoli in virgola mobile sono intrinsecamente approssimati ... non puoi farci nulla se non accettarli (o non usarli).

    Per quanto riguarda il differente comportamento tra la dichiarazione esplicita delle variabili (quindi sei tu che 'tipizzi' le variabili) e la dichiarazione implicita (quindi è Excel a farlo al tuo posto) dovrebbe semplicemente essere che Excel utilizzi delle variabili double invece che single, generando quindi un risultato diverso (sempre a causa dell'imprecisione delle variabili in virgola mobile).

  3. #3
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    16,215
    Blogs
    5
    Fra l'altro Marius il valore 0.1 è uno tra quelli che bon possono essere perfettamente rappresentati in binario. Quindi il suo uso riperuto induce errori grossolani.
    È possibile usare valori interi nei cicli per fare le stesse cose.
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

  4. #4
    Marius44 non è in linea Scolaretto
    Luogo
    Catania
    Post
    312
    Salve a tutti
    Son contento che con la mia ignoranza ho "solleticato" i guru.

    Si, il motivo per cui non esegue a dovere il ciclo è proprio quello indicato da AntonioG e da Max.Riservo

    La mia seconda soluzione è quasi uguale a quella indicata da Max mentre la prima (per ovviare alla "imprecisione" dei valori in virgola mobile) prevede l'utilizzo della Funzione Round per quanto attiene il valore da inserire nel Foglio (che, ovviamente, si ripercuote sul ciclo). Eccola la macro
    codice:
    Sub PrimaSoluzione()
    Range("D:E").ClearContents
    Nr = 0
    Do
      a = a + 1
      Cells(a, 4) = Nr
      Nr = Round(Nr + 0.1, 1)
    Loop While Nr <= 1.4
    End Sub

  5. #5
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    16,215
    Blogs
    5
    Quando i cicli lavorano con gli interi sono più veloci e precisi. Non c'è motivo per utilizzare contatori in virgola mobile, tanto meno funzioni che lavorano su reali.
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

  6. #6
    L'avatar di @Alex
    @Alex non è in linea Very Important Person
    Post
    15,997
    Magari dichiara le variabili... altrimenti sono Variant inutilmente... e mi pare tu non abbia ascoltato i suggerimenti... Usa Nr come Integer o Long a seconda di che dimensione devi raggiungere e poi dividilo solo quando riempi la Cella formattandolo come meglio ritieni.
    Ovviamente credo che [a] sia meglio Byte... anche se integer risulta più performante.
    @Alex
    Il CROSSPOST è VIETATO
    Mirror al vecchio sito WEB(salvare i Demo riassegnando l'estensione (.Zip/.Rar/.Exe in base all'icona...):
    http://mirror.masterdrive.it/alessandrobaraldi/
    Leggi il
    Regolamento del Forum e nel comprenderne la filosofia rispettalo.

+ Rispondi al Thread

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi