Newsgroup: it.comp.lang.pascal
Titolo: baco nel compilatore?

Salve a tutti. Vorrei conoscere il vostro parere riguardo ad una strana
faccenda:
Nel listato di un semplice programma in Pascal č presente un'operazione del
tipo
    r:=somma*(y-55) div 1000;
con : somma>= 200
         y=479 (č una costante)
        r di tipo longint
Fin qui niente di strano, senonchč il risultato a volte č negativo!
Controllando con il Watch le condizioni che vi ho fornito si verificano
*sempre*
"...Vabbč..." direte voi "...probabilmente 'sto tipo ha cannato qualcosa
prima o dopo
 dell'assegnazione..."
ma il bello di tutta la storia č che dividendo l'operazione in 3 parti
(sempre con gli stessi valori)
 r:=somma;
 r:=r*(y-55);
 r:=r div 1000;
tutto funziona alla perfezione!!!
PS: il listato č stato provato su due PC differenti
Cosa ne dite?
Igor

 PS: il listato è stato provato su due PC differenti
[CUT]
si vede che fa molto caldo ~:-))
Ciao ReDiCuori
------------------------------------------
pascal su IRC : #turbopascal
pascal sul web : 
www.pascallike.cjb.net
------------------------------------------

 si vede che fa molto caldo ~:-))
Mi associo!  :)
Ciao
Alex
email: 
el_co...@libero.it

Il problema e' interessante (yuk!)
Premesso che posso sbagliarmi, un compilatore fa' com'e' ovvio anche 
delle assegnazioni invisibili, oltre a quella che gli imponi. Quindi da 
registro a stack, da stack a registro temporaneamente...eccetera, per fare 
i calcoli di un espressione. 
Orbene, in C tutto questo e' ben definito dal linguaggio, ogni manuale 
decente fa un accenno a queste cose, in pascal non so come funzioni,
ma ogni implementazione del linguaggio ha un tipo base intero (int) che
e' grande esattamente quanto sono grandi i registri della macchina (o
eventualmente quando sono grandi le parole dello stack della cpu, se
la macchina e' a stack e non a registri) e che viene usato come tipo jolly,
cioe' per fare qualsiasi calcolo fra costanti, ad esempio, tutte le volte 
che non ci sono dichiarazioni specifiche che indicano il contrario.
Ad esempio se dico 10*y con y int il risultato sara' necessariamente un int
anche se per pura sfiga 10*y darebbe overflow; quindi il programma si 
trovera' in una condizione unpredictable, cioe' variabile da sistema a
sistema. 
Ma veniamo a noi:
Il turbo pascal ragiona in termini di interi a 16 bit, per cui il tipo base 
per le operazioni, quando non e' specificato esplicitamente, e' a 16 bit.
Ora, supponendo che "somma" e "y" siano entrambe di tipo Integer,
(se y fosse una costante simbolica lo sarebbe a prescindere, se compresa 
fra -32768 e 32767) si avra' che:
(y-55)     : integer  quindi  fra -32768 e 32767
somma*(y-55)   : ancora integer
somma*(y-55) div 1000 : pure integer, perche' il cast per essere messe in
r che e' longint viene fatto alla fine delle operazioni, e mi sembra giusto 
visto che l'assegnazione ha la piu' bassa priorita'.
Detto in parole povere, anche perche' e' tardi e sono stufo di dissertare,
il tuo programma va in overflow durante il calcolo somma * risultato di 
(y-55), perche' sta lavorando con interi a 16 bit, e con ogni probabilita'
il risultato di quel calcolo temporaneo e' troppo grande (o troppo 
piccolo). Se poni "somma" come longint dovresti risolvere il tuo problema, 
a meno che tu non stia lavorando con numeri con piu' di 10 cifre, dove 
anche i longint non basterebbero +. Facendo un passo alla volta aggiri 
questo problema, in quanto obblighi il compilatore a fare il cast a longint 
ad ogni calcolo, per questo ti funziona.
Dopotutto, forse basta che fai cosi':
r:=longint(somma)*(y-55) div 1000;
che in C, giusto per dire, suonerebbe cosi':
r=(long int)somma*(y-55) / 1000;
Simpatici quelli che hanno inventato il C, non vi pare?
hanno cambiato il posto dove mettere le parentesi!!! (yuk!)
(bisognava aggiungere un po' di frutta esotica, no?)
Vedo gia' la nebbia e forse la vede anche chi ha letto fino a qui...
meglio andare a letto.
Buonanotte.
Ps: se sbaglio fammi sapere (e come non potresti, dopo tutto questo
decantare???)

E' probabile che ti diventa negativo perchè si verifica un overflow con
numeri troppo grandi e non hai settato l'opzione per l'abilitazione degli
errori di overflow.
Per controllare questa cosa, imposta il compilatore per segnalarti gli
overflow, così quando c'è un overflow, andrà in crash il programma col
classico errore di runtime.
--
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                           Giovanni Ceglia
                WebMaster & WebDesigner
 
http://www.xungame.com/
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 Anche io ho notato questo...
[cut]
Credetemi se vi dico che non è un  problema di overflow, perchè abbiamo
provato anche con
variabili di tipo real e double ed extended (modificando a dovere
l'espressione) e (indovinate?)
risultato negativo!!!
Sono anch'io pienamente consapevole che dividere un'espressione in più parti
ha poco senso (in questo caso)
visto che quest'operazione dovrebbe farla proprio l'elaboratore. Sarà che
gli serve un aiutino...
byez