ragazzi succede una cosa strana quando faccio questa somma in javascipt:
alert((45.08)+(12.77));
il risultato è: 57.849999999999994
ma come è possibile?
se invece faccio:
alert((45.07)+(12.78));
ottengo:
57.85
non capisco
grazie per l'aiuto
ragazzi succede una cosa strana quando faccio questa somma in javascipt:
alert((45.08)+(12.77));
il risultato è: 57.849999999999994
ma come è possibile?
se invece faccio:
alert((45.07)+(12.78));
ottengo:
57.85
non capisco
grazie per l'aiuto
per la stessa ragione di questo codice fatto in Excel
Option Explicit
Private Sub prova()
Dim i, n
n = 0
For i = 1 To 10
n = n + 0.1
Next
Debug.Print (n) '==> stampa 1
Debug.Print (n = 1) '==> stampa false
End Sub
la prima istruzione Debug.Print (n) stampa 1
la seconda istruzione Debug.Print (n = 1) stampa false perchè il risultato non è 1 ma un numero che gli avvicina molto.
In altre parole, non è possibile rappresentare in maniera esatta i numeri in formato in virgola mobile e i calcoli soffrono di questo. Perciò, il risultato lo devi arrotondare te
Pietro
che palle però
grazie
La matematica in JavaScript è "rotta", sin dalla nascita, uno dei fix che verrà fatto in JS 2.0 se mai e/o quando uscirà.
Per avere precisione basta usare i metodi di Number appositi, tipo toFixed oppure toPrecision, stan li apposta per evitare problemi.
alert(parseFloat(((45.08)+(12.77)).toFixed(2)));
57.85
P.S.
pietro ... 1 è 1, non un numero vicino ad uno, ora che Microsoft giustifichi le porcate Ok, ma che pure tu ci credi no eh
Edit P.S.2
non a caso in C# 1.0 == 1 ... per il semplice fatto che l'altro comportamento è semplicemente errato
ma scusa, visto che si usa da sempre questo sistema, non ti sembra che forse sia un buon sistema?Originariamente inviato da Lukem
che palle però
grazie![]()
Pietro
Gentilissimo Andrea, è proprio vero che anche gli Dei cadono e anche su cose banali :P.S.
pietro ... 1 è 1, non un numero vicino ad uno, ora che Microsoft giustifichi le porcate Ok, ma che pure tu ci credi no eh
Edit P.S.2
non a caso in C# 1.0 == 1 ... per il semplice fatto che l'altro comportamento è semplicemente errato![]()
Questo codice in c#, che tu conosci bene![]()
funziona come funzionano tutti i programmi che usano i numeri in formato in virgola mobilecodice:protected void Page_Load(object sender, EventArgs e) { double n = 0; for (int i = 1; i <= 10; i++) n += 0.1; Response.Write(n.ToString() + " "); // stampa 1 Response.Write((n == 1).ToString() + " "); // stampa false }
La somma di 0.1 per 10 volte viene arrotondata a 1 ma la seconda istruzione mi dice che quella somma non è 1 ma 1 a meno dell'errore del sistema di rappresentazione in virgola mobile. La rappresentazione esatta di numeri decimali in virgola mobile è possibile solo per alcuni (non ricordo la regola, ma credo che uno sia 0.125)
I calcoli esatti si fanno ma con gli interi, con i decimal
ps. nozioni che riportano i testi sacri, fin dai tempi dei tempi
un link a wikipedia non si nega a nessuno![]()
http://it.wikipedia.org/wiki/Virgola_mobile
http://bonda.cnuce.cnr.it/Documentat.../parte4_7.html
Pietro
non ho testato niente ma so per certo che in C#
1.0 == 1
è assolutamente true
il punto del 3D è che a lui stampa troppe cifre dopo la virgola, che è il motivo per cui tutti hanno detto da sempre che la matematica in JavaScript è rotta e gli stessi sviluppatori hanno previsto di correggerla nella 2.0
In C# se fai + 0.1 per 10 volte e fai un Console.WriteLine ti da 1, non 0.988898887723 ... fin qui, almeno, spero che siamo d'accordo .. per il resto non ho tempo di testare ma lo farò, soprattutto un confronto di .1 * 10 == 1.0 ... se mi da false, la matematica in C# è rotta, del resto è ECMA pure lui![]()
se sommi 0.1 per 10 volte, viene stampato 1 ma quello è un arrotondamento perchè quella somma non si può fare in maniera precisa con i numeri a virgola mobileOriginariamente inviato da andr3a
non ho testato niente ma so per certo che in C#
1.0 == 1
è assolutamente true
il punto del 3D è che a lui stampa troppe cifre dopo la virgola, che è il motivo per cui tutti hanno detto da sempre che la matematica in JavaScript è rotta e gli stessi sviluppatori hanno previsto di correggerla nella 2.0
In C# se fai + 0.1 per 10 volte e fai un Console.WriteLine ti da 1, non 0.988898887723 ... fin qui, almeno, spero che siamo d'accordo .. per il resto non ho tempo di testare ma lo farò, soprattutto un confronto di .1 * 10 == 1.0 ... se mi da false, la matematica in C# è rotta, del resto è ECMA pure lui![]()
infatti la differenza tra 1 e n è circa 1e-16codice:double n = 0; for (int i = 1; i <= 10; i++) n += 0.1; Response.Write(n.ToString() + " "); // stampa 1 Response.Write((n == 1).ToString() + " "); // stampa false Response.Write((Math.Abs(n - 1)).ToString() + " "); // stampa 1,11022302462516E-16
ti rimando ai link wikipedia più sopra
Pietro
allora, Python 2.5 (che sotto sotto è C) da console (per fare na prova rapida)
1.0 == 1 #True
.1 + .1 == .2 #True
.2 #0.200000000000001
.1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 == 1.0 # False
ma
.1 * 10 == 1.0 #True
e
.1 + .1 + .1 + .1 + .1 + .1 + .1 == .7 # True
quindi da una parte pensavo erroneamente che C# facesse correzioni in automatico (più che C# la VM sotto), dall'altra aggiungere un float statico per N volte non ha senso quindi non mi sono mai interessato troppo al comportamento
il fatto è che i problemi in virgola mobile li conosco ma i problemi in vorgola mobile con linguaggi interpretati non li capisco, partendo da JavaScript, continuando con Python, arrivando a C# che ha una VM sotto ... buono a sapersi, motivo in più per continuare ad usare le funzioni apposite come toFixed e toPrecision![]()