Newsgroup: it.comp.programmare.win32
Titolo: free pascal e real

Ciao a tutti. Premetto che non sono un programmatore esperto.
Sto facendo un semplice programmino con free pascal 2.0 ma mi succede un
odioso problema. Riporto qui semplicemente
var r:real;
begin
    r:=18.36;
    if r<>18.36 then
        write('noooooo!!!')
               else
        write('ok');
    readln;
end.
a video appare la scritta nooooo, infatti osservando con il watch in 
debug alla variabile r viene assegnato il valore 18.35999999999.
Ho provato a mettere la variabile single o extended o anche float con la
unit math. Niente da fare. Tra l'altro ho verificato che la stessa cosa 
succede con il turbo pascal 6.0 sotto dosbox.
Avete qualche suggerimento per risolvere il problema o metterci una "pezza"?


Il problema deriva dall'arrotondamento dei real .... ovvero il numero 
contentuto nella variabile non è e non potrà mai essere 18.36 ma è una 
sua approssimazione in potenze di 2.Una soluzione potrebbe essere fare 
una uguaglianza non della variabile ma dell'arrotondamento alla cifra 
significativa dei 2 campi. Non mi ricordo come si chiama in pascal la 
funzione di arrotondamento , cmq ti suggerirei qualcosa tipo 
round(r*100)<>1836 ..... ma potrei sbagliare-

 round(r*100)<>1836 ..
Ci avevo pensato a una soluzione del genere ma ho il problema che non so 
a priori con quante cifre decimali ho a che fare (potrebbero variare da 
2 a 10) e non posso arrotondare troppo altrimenti mi si sballano i 
confronti.
Non mi resta che stabilire dei criteri per impostare il valore del 
moltiplicatore (100, 1000, 10000 ecc...), oppure metterne uno molto alto 
(se mi basta la memoria)...
Sembra impossibile che un compilatore si incasini in un problema cosě 
semplice. Succede anche in C o altri linguaggi?
Grazie comunque della risposta.

Fdan ha scritto:


prendi il valore assoluto della differenza tra i due valori da confrontare
e lo confronti con una tolleranza di tua scelta.
Se č minore li consideri uguali.
es.
toll = 0.0005
se abs(a - b) < toll
    i valori sono uguali
altrimenti
    i valori sono diversi 
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Grazie comunque della risposta.

 e lo confronti con una tolleranza di tua scelta.
E' una bella idea ma le tolleranze sono variabili a seconda dei valori.
Per es. se ho n>10 la tolleranza sarà 0.01, se n<1 sarà 0.001 ecc...
Diventa troppo complicato. Mi conviene prendere la tolleranza minima, 
fare l'inverso, e usare quello come moltiplicatore per tutti i valori.
Tipo 1/0.000001=1000000   1000000*18.36=18360000

 numero di cifre significative delle misure che tu vai a prendere 
Certo, avevo tenuto conto di questo, non mi piace sprecare risorse ;-)

Fdan ha scritto:

mi sa che non hai capito qual'è il problema.
La tolleranza serve solo per compensare la mancanza di precisione dovuta 
all'impossibilità di rappresentare un numero reale nella sua completezza 
(adattato invece al modulo 2).
<cite>
a video appare la scritta nooooo, infatti osservando con il watch in 
debug alla variabile r viene assegnato il valore 18.93599999999.
</cite>
come puoi vedere dal tuo esempio la tolleranza può essere anche 0.0000000005
quindi:
  r:=18.36;
  [abs(18.36 - r) < 0.0000000005] => 18.36 == r
poi considera che nella tua soluzione, se use valori real, il problema 
permane. Se usi interi puoi incorrere nell'overflow del dato.

test
