Newsgroup: it.hobby.enigmi
Titolo: Quesito di Visual Basic

Scusate se vi sottopongo un quesito un po' specialistico e anomalo per
questo NG.
Le seguenti righe generano in Visual Basic 6.0 un errore di overflow:
Dim i as Byte
For i = 10 To 1 Step -1
    Print i
Next i
Sapreste motivare il perché?
Ciao :-)
Giorgio

 ha scritto:

Credo di si'.
Per il VB la variabile Byte e' unsigned, definita nel campo 0..255.
Per compilare "For i = 10 To 1 Step -1" deve eseguire 10 + (-1)
e (-1) e' fuori dal range di definizione. E' il vantaggio/svantaggio
di un linguaggio ad alto livello, avere piu' controlli.
Questo fa la stessa cosa, senza errori:
Dim i As Byte, j
For j = 10 To 1 Step -1
    i = j
    print i
Next j
Ciao!!!  ((^__^))'
Livio


Ciao Livio!
Non è del tutto esatto...
Se scrivi:
Dim i as Byte
i = 10
i = i -1
anche in questo caso c'è un 10 + (-1) eppure non vengono generati errori.
Non solo. Il ciclo For che ho riportato dovrebbe essere semanticamente
equivalente a questo ciclo while:
    Dim i As Byte
    i = 10
    Do While i >= 1
        Print i
        i = i - 1
    Loop
eppure quest'ultimo funziona - quindi non sono semanticamente equivalenti!
:-)
Ti dirò di più. Se provi a eseguire il ciclo For passo passo, noterai che
l'errore viene generato alla prima esecuzione della riga:
For i = 10 To 1 Step -1
e non successivamente, quindi il decremento non è ancora stato eseguito.
E' chiaro che il problema sta in quel -1 che è fuori dal range del Byte. Ma
perché genera un errore? Se VB si limitasse a utilizzare il valore dello
Step per aggiungerlo alla variabile del For alla fine del ciclo, il
risultato sarebbe la generazione dell'istruzione i = i - 1, che, come
abbiamo visto, non dà problemi. Invece cosa succede veramente?
Ciao :-)
Giorgio

 abbiamo visto, non dà problemi. Invece cosa succede veramente?
Posso fare solo una illazione, perche' non ho scritto io il compilatore 
del VB :-)
Una possibilita' e' che quando entra nel ciclo il compilatore
si accorge che lo step e il limite sono delle costanti,
allora predispone due locazioni (dello stesso tipo dell'indice di ciclo) 
in memoria contententi 10 e -1 che verranno poi utilizzate ad ogni ciclo 
per confronto e incremento.
Solo che ovviamente il -1 intero nel byte unsigned non ci sta
tanto bene....si tratta di un bel baco !
Secondo me non hanno previsto che uno utilizzasse come
indice di un ciclo a decrementare una variabile byte.
(diciamo che in ogni caso e' una cosa abbastanza rara:
a parte il risparmio di spazio quando uno alloca un
array di grandi dimensioni, per i calcoli e gli indici
di ciclo direi che e' quasi sempre meglio usare numeri
interi anziche byte perche' spesso sono piu' veloci da trattare
per la cpu anche se sono piu' "lunghi").
g.

non può essere che legga -1 come 255, e quindi veda che l'incremento è maggiore dell'intervallo???

 e non successivamente, quindi il decremento non č ancora stato eseguito.
Certo. E' gia' overflow il valore dello step.
E ti diro' di piu'. Se fai:
Dim i as Byte, j
i=10
j=-1
i=i+j
non c'e' di nuovo alcun errore di overflow. Perche'?
Perche' il VB assume come variabili di servizio delle variabili
che abbiano un'estensione pari a quella maggior in gioco nel
calcolo, in questo caso quella di j, simple. Solo alla fine
dell'operazione assegna il risultato alla variabile i e da' l'overflow
solo se il risultato e' fuori range.
Ma il basicsta si chiede: perche' usare variabili tipo Byte quando
l'ultimo dei Pentium lavora su un parallelismo di 64 bit ed esegue
un'operazione in un ciclo macchina e un ciclo macchina in un
colpo di clock?
Ciao!!!  ((^__^))'
Livio

 per la cpu anche se sono piu' "lunghi").
Su questo sono perfettamente d'accordo. Mai usare un byte al posto di un
intero, credendo di risparmiare. Perň ne avevo bisogno per il quesito! :-)
Ciao :-)
Giorgio

 dell'indice e con quelle fare i confronti e gli incrementi.
Mica d'accordo!  :o)))
(...sul fatto che sia un baco. L'e' che come si trovano due cplusplusisti,
subito a dar in testa al basic!)
Che dimensione dovrebbe assegnare allo step, ad es., una routine
come questa?
Dim Di as Date
For Di = #December 31, 2002# To #January 1, 2003# Step 0.25
       Print Di
Next Di
E una routine come questa avrebbe ragione o no a tirare fuori
un overflow?
Dim A as integer, B as integer, C as simple
A=30000
B=30000
C=A*B
Ciao!!!  ((^__^))'
Livio


I tuoi esempi mi vanno benissimo (a parte il tipo simple, che nel mio Visual
Basic 6.0 non c'è, ma forse tu hai una versione speciale fatta per i
fedelissimi... ;-)))) )
Quello che segue non dà errori, nonostante ci sia un operazione tra Integer
che coinvolge un valore 40000, che in un Integer non entra:
Dim a as Integer
a = -20000
a = a + 40000
allora perché non dovrebbe funzionare questa:
Dim a as Integer
For a = -20000 to 0 Step 40000
Next
Se VB si limitasse a trasformarlo in:
a = -20000
Do While a <= 0
    a = a + 40000
Loop
funzionerebbe ugualmente.
Invece VB lo trasforma pressappoco in:
Dim aux1 as Integer
Dim aux2 as Integer
aux1 = 0
aux2 = 40000    ' qui si verifica l'errore di overflow
a = -20000
Do While a <= aux1
    a = a + aux2
Loop
Non ti sembra una perdita di tempo? :-)
P.S. In 
VB.NET
 le cose sono state un po' sistemate. Il modo di trasformare
il For è rimasto (purtroppo) lo stesso, però l'istruzione incriminata:
Dim i as Byte
For i = 10 To 1 Step -1
produce un errore di sintassi sul -1 al posto dell'errore run-time di
overflow. Un piccolo passo avanti! :-)
Ciao :-)
Giorgio

 Next
Perche' per dimensione di start, end e step viene forzata la
dimensione del counter. Ma non potrebbe far diversamente in
una programmazione ad oggetti.
Pero'... c'e' di peggio! La piu' sconcertante per me e' questa:
Dim A as Integer, B as Single
A=30000
B=A+40000
*** tutto OK ***
Dim A as Integer, B as Single
A=30000
B=A+30000
*** Overflow! ***
Com'e' possibile???
.
.
.
.
.
.
.
.
.
.
.
spoiler   :o)))
.
.
.
.
.
.
.
.
Nel primo caso per 40000 VB non puo' fare a meno di assegnare
una dimensione implicita Single, quindi il target e' Single.
Nel secondo caso puo' farne a meno e lo fa! Il target resta Integer
e l'operazione va in errore!
Ciao!!!  ((^__^))'
Livio


Questo aspetto, con la programmazione a oggetti, ha ben poco a che vedere.
La scelta di immagazzinare i valori del termine finale e dello step
all'interno di variabili temporanee è assolutamente arbitraria. Il VB lo fa
e lo porta avanti in maniera coerente, ma se non lo facesse, il
comportamento del for sarebbe molto più comprensibile.
Esempio:
Dim i as Integer, n as Integer
n = 10
For i = 1 To n
    Print i
    n = n - 1
Next
A occhio diresti che stamperà i numeri da 1 a 5 (i sale e n scende, più o
meno si incontreranno a metà strada), ma qui siamo in Visual Basic, non
sempre tutto funziona secondo la logica (e infatti stampa i numeri da 1 a
10)! :-))))
Ciao :-)
Giorgio

 subito a dar in testa al basic!)
Vorrei solo far presente che
1) NON SONO ASSOLUTAMENTE UN CPLUSPLUSISTA. Rifuggo come la
peste i linguaggi ad oggetto a meno che non sia costretto ad
usarli (tipo per programmare il Verbatron sotto Windows). Anche
in quel caso in pratica uso il c++ solo per le interfacce con l'utente.
(Non per denigrare il c++, ma e' che avendo cominciato a programmare
a 13 anni (25 anni fa', ahime'...) su linguaggi non-a-oggetto sono
troppo vecchio per cambiare mentalita')
2) Quello del FOR a me sembra un proprio un baco: o la sintassi del 
comando e' giusta e il compilatore non effettua correttamente un
decremento, oppure dovrebbe segnalare a tempo di compilazione che
lo step non e' di tipo corretto, visto che puo' benissimo
fare il controllo staticamente. Anche questo non per denigrare:
e' difficile trovare un compilatore assolutamente privo di
errori.
ciao,
g.