Newsgroup: it.comp.lang.visual-basic
Titolo: la matematica e' un' opinione

Vi e' mai capitato che il vb non riesca a fare degli apparentemente semplici
calcoli?
Provate a scrivere qualcosa del genere:
dim a1 as double, a2 as double, a3 as double, a4 as double
a1=100
a2=99.95
a3=99.9
a4=99.85
e' evidente che la differenza tra questi valori e' sempre 0.05, ma se
scrivete anche:
debug.print a1-a2; a2-a3; a3-a4
quello che si ottiene e':
4.99999999999999972E-02 4.99999999999999972E-02 5.000000000000000114E-02
Sapete perche' e, soprattutto, come correggere?
Ciao. g.

 Sapete perche' e, soprattutto, come correggere?
L'argomento direi che ormai è stato trattato un numero infinito di volte.
I computer non ragionano in base10, come noi umani. Ragionano in base2. Ogni
tipo di variabile garantisce un determinato tipo di conversione da decimale
a binario.
Se ti interessa la miglior rappresentazione in formato decimale, rinunciando
però a precisione maggiore in ambito scientifico, ti conviene usare un tipo
Currency. Se usi double, il valore viene visualizzato 'male' quando ne
chiedi una conversione in decimale, in quanto double arrotonda ad una
posizione dopo la virgola molto lontana, mentre currency è più 'grossolano'.
Se fai la prova che hai postato, dimensionando come currency, tutto verrà
come vuoi tu.
Alberto

 Sapete perche' e, soprattutto, come correggere?
Hai urgente bisogno di studiare. Potresti cominciare dalla guida:
    MSDN Library Visual Studio 6.0
    - Documentazione di Visual Basic
      - Utilizzo di Visual Basic
        - Manuale del programmatore
          - Nozioni fondamentali di Visual Basic
            - Nozioni fondamentali sulla programmazione
              - Variabili, costanti e tipi di dati
                - Tipi di dati
e da un buon manuale scolastico di programmazione.
--
Ciao.
Maurizio
--------
?SPQR(C)
 X
--------


Ti faccio notare che, entro i limiti di tolleranza, il risultato che hai
ottenuto e' sempre quello corretto: 0.05!
Per risolvere il problema (se n'e' parlato in post precedenti) la stessa
MSDN consiglia di effettuare un test (cito da un post di hal1961 - un uomo
un mito :) - che a sua volta citava qualcun'altro):
<citazione>
1.
HOWTO: Work Around Floating-Point Accuracy/Comparison Problems
Q69333
http://support.microsoft.com/support/kb/articles/Q69/3/33.ASP
da cui estraggo questo incipit:
To reliably test whether two floating-point variables or expressions are
equal
(using IEEE format or MBF), you must subtract the two variables being
compared
and test whether their difference is less than a value chosen at the limits
of significance for single or double precision.
NO OTHER TEST FOR EQUALITY WILL BE RELIABLE.
</citazione>
che puoi facilmente trasformare relativamente al tuo caso.
Se gia' conosci la precisione con cui vuoi ottenere un risultato, potresti
usare l'istruzione round che serve appunto ad arrotondare una cifra con il
numero di cifre significative che ti interessa.
Nella maggior parte dei casi di _mio_ interesse, sei cifre significative
vanno piu' che bene. Prova cosi':
Dim a1 As Double, a2 As Double
a1 = 100: a2 = 99.95
Debug.Print a1
Debug.Print a2
Debug.Print (a1 - a2)
Debug.Print Round(a1 - a2, 6)
Otterrai il risultato corretto.
Leggi l'interessantissimo thread "30,7 - 30 = 0,6999999999 xche????"
iniziato da Giuseppe Anicito il 08/04/02.
Ciao,
- SonicBoom -

 Sapete perche' e, soprattutto, come correggere?
si , si , lo sappiamo , un mesetto fa ci siamo stomacati con sta storia ...
guarda qui : 
group.google.com

| Leggi l'interessantissimo thread "30,7 - 30 = 0,6999999999 xche????"
| iniziato da Giuseppe Anicito il 08/04/02.
| Ciao,
Grazie a te ed agli altri che mi hanno risposto, siete stati davvero
gentili.
g.

 calcoli?
[CUT]
Penso che questo mio post di qualche tempo fa
sia abbastanza esaustivo:
http://groups.google.com/groups?q=non+rappresentabile+in+binario+group:it.co
mp.lang.visual-basic&hl=it&lr=&selm=8psh0v%24f2u%241%
40nslave2.tin.it
&rnum=1
Proposta:
Se riesco a fare un piccolo riassuntino dei miei ricordi
di calcolo numerico si può mettere sul sito comune
così molti possono andare lì e capire
il perchè il "computer sbaglia a fare i conti?"
                                    danilo
Fatemi sapere.

[CUT]
Ovviamente il link è su un'unica riga
http://groups.google.com/groups?q=non+rappresentabile+in+binario+group:it.co
mp.lang.visual-basic&hl=it&lr=&selm=8psh0v%24f2u%241%
40nslave2.tin.it
&rnum=1

| Grazie a te ed agli altri che mi hanno risposto, siete stati davvero
| gentili.
|
| g.
Aspe', ferma!
Mi capita la stessa cosa se importo un numero in un database e poi lo vado a
riprendere:
dim a as double, b as new adodb.recordset
a=0.1
b=a
a=b
alla fine ottengo che a e' diverso dal valore che gli avevo dato.
E' possibile evitare di inserire una funzione di arrotondamento *per ognuna
delle 10.000 operazioni matematiche*?
Secondo voi per avere un numero minimo di cifre significative dopo la
virgola mi conviene arrotondare ogni volta oppure usare il tipo currency
spostando la virgola artificialmente con operazioni di moltiplicazioni e
divisioni per 1.000 o 1.000.000 oppure...?
Grazie ancora.
g.

 alla fine ottengo che a e' diverso dal valore che gli avevo dato.
Scusa, ma hai dimensionato b come Adodb.Recordset?
Alberto

 ha scritto nel messaggio
news:ac2lci$s4t$1...@newsreader.mailgate.org...

No, per semplicita' non ho inserito tutto il codice che definisce la
variabile
b... (che e' un elemento di un recordset).

 b... (che e' un elemento di un recordset).
Cioè, esattamente di che tipo?
Comunque, tornando al discorso iniziale:
La cosa migliore, in termini di precisione, è sempre utilizzare variabili ad
alta precisione, ad esempio double.
Siccome tutte le forme di rappresentazione (Label.Caption, TextBox.Text,
....) sono sempre di tipo stringa, è comunque scorretto utilizzare delle
cose tipo:
Dim A as double
A=10.20
Text1.Text=A
mentre occorre usare Text1.Text=Cstr(A)
Ma anche questa modalità potrebbe essere scorretta, in quanto dipendente
dalle impostazioni internazionali. Conviene sempre avere una funzioncina che
formatti il valore della variabile numerica in stringa, ad esempio il format
stesso:
Text1.Text=Format(A,"#,##")
Quello che occorre considerare è che il tuo problema è SOLO di
presentazione, non di memorizzazione. Continua pure a gestire le variabili
come ti pare. Ricorda solo che non bisogna usare mai le variabili numeriche
o booleane come se fossero stringhe.
Ciao
Alberto

 o booleane come se fossero stringhe.
Traduci, per favore. Questo passo mi risulta oscuro.


 Traduci, per favore. Questo passo mi risulta oscuro.
Non è difficile.
Alberto

 Non è difficile.
Pazienza.
