Autore Topic: Ciclo For...Next che gira all'infinito  (Letto 1725 volte)

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.317
  • Ne mors quidem nos iunget
    • Mostra profilo
Ciclo For...Next che gira all'infinito
« il: 01 Ottobre 2012, 23:17:39 »
...l'avevo notato anche qualche altra volta, ma non vi avevo dato peso più di tanto; ultimamente mi sono imbattuto nuovamente nel ciclo For...Next da 0 a 255 con variabile di tipo Byte che  gira all'infinito:
Codice: gambas [Seleziona]

Public Sub Button1_Click()

  Dim j As Byte

  For j = 0 To 255

   Print j

  Next

End



Ho posto la questione nella Mailing List Internazionale, poiché nella mia asinità temevo un bug, ma non è così, e ne è nata un discussione (che tra l'altro non mi attendevo) fra più utenti, che vorrei qui riportare (nel timore di commettere errori di traduzione, riporto i messaggi nella lingua originaria in cui sono stati scritti):
«Just guessing here, but valid values for Byte are 0-255. From
observation I have seen that FOR loops terminate with the loop index
at final value+1. For Byte that would probably be zero (if it just
wraps around from 255 to 0) so there is no reason to terminate the
loop.

Richard
»

«Can confirm that with rev5189. Richard's guess sounds logical. "For To" is
inclusive: [0; 255] and that's everything you can represent with Byte width.
You won't ever detect Byte > 255.
Tobias Boege
»

« I think all Basics work this way!

Test with any basic:

For ii = 1 to 10
Next

Print ii

What you expect? I think all basic languages gives 11 as result.

Jussi Lahtinen
»


«Sinclair BASIC on the QL used to have a FOR loop epilogue which could
be used to handle this sort of thing. A simple FOR loop was

FOR index = start TO stop

Sinclair BASIC on the QL used to have a FOR loop epilogue which could
be used to handle this sort of thing. A simple FOR loop was

FOR index = start TO stop
      do some stuff
END FOR index

The NEXT control could be added to create the epilogue so:
FOR byte = 0 TO 254
      PRINT index
NEXT index
      PRINT index
END FOR index

Would print out the values from 0 to 255. If the loop's initial
conditions would not permit execution, control jumps to after the END
FOR marker.

It also allowed :

FOR index = 0 TO 15, 64, 96, 128 to 254, 255

Very useful, and just one of the many features I miss from SuperBASIC.

richard.j.walker
»

« It is the same in almost all languages.

Codice: c [Seleziona]
unsigned char i;
for(i=0; i<255; i++){}
and
unsigned int i;
for(i=0; i<4294967295U; i++){}

in C will never terminate.

In Gambas,

Codice: gambas [Seleziona]
Dim i As Integer
For i = 0 To 2147483647
Next

will not terminate either.

You might think that because you say the range 0 To X, you expect to get
each of those values, but the truth is that the For i = 0 To X is actually
interpreted as for(i=0; i<=X; i++) which obviously does not work when X is
the max value of that integer type.

emil.lenngren
»

« This same thing is simpler in Gambas:

Codice: gambas [Seleziona]
For ii = 0 to 254
Print ii
Next
Print ii


Jussi Lahtinen »

« Problem with that is that the second "Print ii" statement is executed,
even if the loop is skipped (because of initial conditions). The
SuperBASIC version would print nothing if the initial loop conditions
indicate it should be skipped

The Gambas equivalent would be more like


Codice: gambas [Seleziona]
For ii = 0 to 254
    Print ii
Next
If (some test by which we can tell the loop has iterated at least once) Then
Print ii
End If


Also, an EXIT statement in the loop would leave the SuperBASIC FOR
loop, skipping the loop epilogue (the bit between the NEXT and the END
FOR).

A better trivial example of the loop epilogue in action might be:

FOR character = 1 to LEN$(test$)
       IF test$(character) == "@" THEN EXIT character
NEXT character
       REMark Character not found
       character = 0
END FOR character

IF character THEN
       PRINT test$(1 TO character-1) & test$(character+1 TO )
ELSE
       PRINT "Not found"
END IF

richard.j.walker
»
« Ultima modifica: 01 Settembre 2014, 00:02:47 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #1 il: 01 Ottobre 2012, 23:45:38 »
La cosa è interessante e pure problematica, perchè riguarda proprio valori che sono potenze di 2, può introdurre problemi di difficile soluzione. ???
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #2 il: 02 Ottobre 2012, 00:07:46 »
...l'avevo notato anche qualche altra volta, ma non vi avevo dato peso più di tanto; ultimamente mi sono imbattuto nuovamente nel ciclo For...Next da 0 a 255 con variabile di tipo Byte che  gira all'infinito:
Codice: gambas [Seleziona]

Public Sub Button1_Click()

  Dim j As Byte

  For j = 0 To 255

   Print j

  Next
End

Secondo me, è naturale che funzioni così. Infatti in un byte si possono ottenere valori esadecimali che variano da 0 a 255, cioé  da "00" a "FF".
Supponiamo che si disponga di un campo binario puro con valore pari a 00FF. Se vi sommiamo "1", otteniamo "0100". Riconducendo il ragionamento alle variabili byte, di lunghezza pari ad 1 byte,  dopo l'ulteriore somma di "1" al valore "FF" otteniamo il valore "00". Ciò dipende esclusivamente dalla limitata dimensione del contatore. É lo stesso effetto del contachilomentri di un'autovettura o di di qualsiasi contatore meccanico, dotato, per esempio,  esclusivamente di 5 cifre. Quando tutte presentano il valore 99999, se vi sommiamo ancora uno otterremmo 00000.

In definitiva, il tuo contatore J non potà mai raggiungere il valore 256 che è quello che determinerebbe la fine del ciclo "For ... Next".

Spero di essere riuscito ad esprimere con la giusta sufficienza il concetto. Se non ci sono riuscito, dimmelo. Cercherò di ripetermi con altre parole.
 :ciao:

:ciao:

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.317
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #3 il: 02 Ottobre 2012, 01:30:58 »
In definitiva, il tuo contatore J non potà mai raggiungere il valore 256 che è quello che determinerebbe la fine del ciclo "For ... Next".
Dalla discussione in M.L.I. e dal tuo intervento mi sembra si possa affermare che "un ciclo, per terminare, deve raggiungere il valore superiore al suo estremo massimo".
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #4 il: 02 Ottobre 2012, 08:16:44 »
Si, é così. Infatti se tu verifichi il contenuto della variabile indice del ciclo di "For ... Next", all'uscita naturale dal ciclo, ti accorgi che il suo contenuto ha raggiunto lo step successivo al valore massimo del ciclo, cioè:
Codice: [Seleziona]
For i = 0 to n
----- bla bla ------
Next
'Ora i contiene "n+1"

Ma tu hai proprio bisogno  di comandare un ciclo  "For ... Next", gestito  da una variabile di tipo byte, oppure la tua prova è nata da una semplice curiosità?
 :ciao:
:ciao:

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.317
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #5 il: 02 Ottobre 2012, 10:33:27 »
Ma tu hai proprio bisogno  di comandare un ciclo  "For ... Next", gestito  da una variabile di tipo byte, oppure la tua prova è nata da una semplice curiosità?

Mah... stavo facendo un semplice esperimento. Solitamente, quando non  devo utilizzare valori superiori a 255, dichiaro sempre variabili di tipo Byte. Per questo, ho notato nuovamente quel comportamento infinito del ciclo. ...ed infatti ho poi usato il tipo di variabile meno dispendiosa di memoria immediatamente superiore al tipo Byte: lo Short.
Solo questo.

Ad ogni modo, da tutta 'sta storia emerge che, se uno per una qualche ragione, ha bisogno di un ciclo infinito, sa c'è anche quest'altra modalità.
« Ultima modifica: 02 Ottobre 2012, 10:35:58 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #6 il: 02 Ottobre 2012, 14:40:19 »
da tutta 'sta storia emerge che, se uno per una qualche ragione, ha bisogno di un ciclo infinito, sa c'è anche quest'altra modalità.

Il tipo di dati "Byte" é una peculiarità di Gambas. Sia nel vecchio GWBasic che nel più recente Visual Basic il tipo di dati "Byte" non esiste. Entrambi contemplano i dati in:
- interi(2 byte)
- a precisione semplice(4 byte)
- a precisione doppia(8 byte)
- currency (in VB gestisce i valori monetari a virgola fissa con max 15 cifre a sinistra e 4 a destra della virgola decimale)
- date(in GWBasic era un formato stringa (date$: mm-gg-aa; mm/gg/aa; mm/gg/aaaa --- in VB invece è di tipo variant e gestisce anche l'ora)
- stringa(per quest'ultimo VB riconosce anche la lunghezza fissa, prestabilita in fase di dichiarazione).
 :ciao:
:ciao:

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #7 il: 02 Ottobre 2012, 16:49:33 »
Non per contraddirti, ma la variabile tipo Date è nata con il VB, nel Quick Basic e precedenti non esisteva, e la stringa a lunghezza fissa esisteva già nel Quick Basic. :)
Ed inoltre dal QB in poi esistevano anche gli interi lunghi a 4 byte.
« Ultima modifica: 02 Ottobre 2012, 21:06:03 da Top Fuel »
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #8 il: 02 Ottobre 2012, 22:28:37 »
Non per contraddirti, ma la variabile tipo Date è nata con il VB, nel Quick Basic e precedenti non esisteva, e la stringa a lunghezza fissa esisteva già nel Quick Basic. :)
Ed inoltre dal QB in poi esistevano anche gli interi lunghi a 4 byte.
Relativamente al Quick Basic non dispongo più di un manuale, quindi sono andato a ricordo. Hai perciò fatto bene a correggermi.

Non concordo invece sull'inesistenza di un tipo di variabile Date in GWBasic. Se hai letto bene la mia nota
Citazione
date(in GWBasic era un formato stringa (date$: mm-gg-aa; mm/gg/aa; mm/gg/aaaa --- in VB invece è di tipo variant e gestisce anche l'ora)
ho espressamente precisato che in GWBasic il tipo di variabile prendeva il nome di "Date$" e che rappresentava solamente la data e non l'ora. Il suo formato era perciò: mm-gg-aa. Ne consegue che la variabile "Date" del VB é la naturale evoluzione della vecchia "Date$".  Se però ancora non mi credi, posso mandarti una fotocopia della pagina del mio manuale GWBasic che tengo gelosamente conservata fra i miei preziosi manuali informatici.

Citazione
Ed inoltre dal QB in poi esistevano anche gli interi lunghi a 4 byte.
Non solo con l'avvento del Quick Basic, esistevano  anche nel GWBasic.

Caro il mio Top Fuel, se scrivo un concetto, al 99% lo faccio dopo essermi documentato.  ;)

Certo può capitare anche un'imprecisione come quella sulle stringhe a lunghezza fissa, nate col Quick Basic. Quella, purtroppo, é sfuggita all'organo di controllo (che poi sono sempre io). ;D

 :ciao:
:ciao:

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.317
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #9 il: 02 Ottobre 2012, 22:57:57 »
Relativamente alla discussione tra voi avviata, c'è il rischio che vada alla lunga fuori tema. Forse sarebbe opportuno che creaste una "discussione" a parte, specifica.


Io, invece, volevo aggiungere un altro intervento sul tema del ciclo infinito For..Next:

« When using Byte data type

The loop iteration when j=255 is 255 + 1 = 0

Thus, the end condition of j>255 can never happen
It is an endless loop.
This 'problem' is correct operation for the datatype used.
This issue arises always at the boundary of the datatype
when math takes it beyond the possible range.

nando
»
« Ultima modifica: 02 Ottobre 2012, 23:33:09 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #10 il: 02 Ottobre 2012, 23:37:15 »
Non concordo invece sull'inesistenza di un tipo di variabile Date in GWBasic. Se hai letto bene la mia nota
Citazione
date(in GWBasic era un formato stringa (date$: mm-gg-aa; mm/gg/aa; mm/gg/aaaa --- in VB invece è di tipo variant e gestisce anche l'ora)
ho espressamente precisato che in GWBasic il tipo di variabile prendeva il nome di "Date$" e che rappresentava solamente la data e non l'ora. Il suo formato era perciò: mm-gg-aa. Ne consegue che la variabile "Date" del VB é la naturale evoluzione della vecchia "Date$".  Se però ancora non mi credi, posso mandarti una fotocopia della pagina del mio manuale GWBasic che tengo gelosamente conservata fra i miei preziosi manuali informatici.

C'era la FUNZIONE Date$ che ritornava in una STRINGA la data corrente, ma non una variabile di questo tipo.
Li ho usati tutti e 2 anche io eh. ;)
Meglio che la piantiamo qui o finiamo a botte (o ci picchia vuott). ;D ;D
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #11 il: 03 Ottobre 2012, 00:01:39 »
la variabile "Date" del VB é la naturale evoluzione della vecchia "Date$".

C'era la FUNZIONE Date$ che ritornava in una STRINGA la data corrente, ma non una variabile di questo tipo.
Li ho usati tutti e 2 anche io eh. ;)
Meglio che la piantiamo qui o finiamo a botte (o ci picchia vuott). ;D ;D

Sicuramente, ma forse più che vuott qualcun altro che mi ha già richiamato una volta.  :D Poi,  in definitiva, anche se da posizioni diverse, siamo arrivati entrambi alla stessa conclusione.  ;D
 :ciao:
« Ultima modifica: 03 Ottobre 2012, 00:03:32 da Picavbg »
:ciao:

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #12 il: 03 Ottobre 2012, 11:58:53 »
mmmmmmmmmmmm.......

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #13 il: 03 Ottobre 2012, 23:06:46 »
Ho provato a fare questa cosa con il Basic PDS 7.1 (il successore del QuickBasic 4.5) usando un integer:
Codice: [Seleziona]
DIM i AS INTEGER
FOR i = 0 to 32767
   PRINT i
NEXT
In ambiente interpretato, alla fine del ciclo mi da correttamente errore di overflow.
Però non ho provato a compilare il programma per vedere che succede.
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Ciclo For...Next che gira all'infinito
« Risposta #14 il: 04 Ottobre 2012, 12:14:22 »
Ad ogni cosa il suo...  :D

Se usiamo un contatore, e il C fà appunto scuola, è necessario fare attenzione alle sue dimensioni.
Ogni variabile ha una sua dimensione specifica, e per alcune dipende anche dall'hardware.
Un esempio è l'int in C, che può essere di 16 o 32 bit. Il long è sempre 32 bit, il float 32 bit, il double 64 bit. Poi ci sono gli extended: long float = 64 bit, long double = 80 bit. Il byte, o char, è di 8 bit.
Insomma, se usiamo un contatore, è necessario sapere che lo scorrimento del bit lungo la dimensione della variabile, alla fine và fuori e và perso. Il contatore, come uso, fà shiftare il bit, da sinistra a destra o viceversa (vedi STEP), mandandolo al termine fuori range (ad es. il Byte è il bit 7). Se il for...next và a loopare su tutta la scala dei bit della variabile, alla fine si ritrova magicamente a zero, perchè il bit è uscito fuori range.
Di norma, per la costruzione di un contatore, o si esegue un pre-controllo sul fuori scala, oppure si usa una variabile contatore più grande. Ad esempio per il Byte (o bit) si può usare un Integer (16 bit), in questo modo si evita di andare in errore.
A volte, potrebbe essere conveniente utilizzare istruzioni mirate sui singoli bit, evitando quindi un loop.