sirtao Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 (modificato) java. JDK 1.6.0-17 su Windows(appena sono a casa testo su linux) public class Primo{ public static void main(String[] argv){ //Variables int varInteger=10; double varDoppio=3.14; varDoppio=varInteger-varDoppio; System.out.print(varDoppio); } } qualcuno mi spiega perche' esce fuori 6.859999999999999 ? ho provato a cambiare i valori, ma viene fuori SOLO con 10 e 3.14(se sia 10 che 3.14 sono negativi, viene -6.859999999999999) Modificato 23 Novembre, 2009 da sirtao Link al commento Condividi su altri siti More sharing options...
jetblack Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 provato a vedere che succede se metti double alla prima variabile? Link al commento Condividi su altri siti More sharing options...
sirtao Inviato 23 Novembre, 2009 Autore Share Inviato 23 Novembre, 2009 A cambiarlo in Double, stesso identico problema. Anche se invece di 10 metto 10.0 o 10.00. System.out.print(10-3.14) mi da' lo stesso risultato. idem System.out.print(10.0-3.14) e System.out.print(10.00-3.14) la cosa ha sempre meno senso... che è un easter egg che non da' il risultato corretto(perche' e' SBAGLIATO) se si sottrae 3,14 a 10? Link al commento Condividi su altri siti More sharing options...
Chibi Goku Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 E se usi float al posto di un double? Link al commento Condividi su altri siti More sharing options...
War3333 Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 Lo fa anche se usi float, e lo fa anche su Java 5 e credo che lo faccia anche su Java 4 evidentemente non è considerato un errore. Link al commento Condividi su altri siti More sharing options...
formatted_brain Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 Mi sembra un problema di precisione. Vedi se questo può esserti d'aiuto. Link al commento Condividi su altri siti More sharing options...
werner Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 (modificato) Non ricordo più molto di Java, quindi non mi ricordo se abbia o meno il concetto di format string o una cosa del genere, nè in che modo stampi un numero reale come default. Il tuo problema è che non arrotonda solo per quella particolare somma (o sottrazione) verso un più leggibile 6.86, oppure non ti gusta che il risultato appaia "sbagliato" leggendo tutti i decimali? No, perchè la conversione da base 10 a floating point base 2 introduce molto spesso degli errori di troncamento (per esempio 0.1 è periodico in base 2...) e dunque se vai a leggere tutta la precisione del numero quasi sempre i risultati di un calcolo in virgola mobile si discostano leggermente dal risultato algebrico. Se poi è un calcolo iterativo puoi perfino avere un errore che diverge se scegli male l'algoritmo, e un risultato finale del tutto insensato: buona parte dei corsi di analisi numerica si occupa proprio di questo problema. E' il motivo per cui l'operatore "uguaglianza" fra due real non si deve usare mai, ma va sostituito da una sottrazione seguita dal confronto con un epsilon scelto sufficientemente piccolo a seconda dell'applicazione... Ah, il metodo di arrotondamento indicato nel link di formatted_brain può anche funzionare, ma sicuramente è lento come la fame e non usabile per altro che l'output a schermo (e anche in quel caso, devono di certo esserci sistemi migliori) Modificato 23 Novembre, 2009 da werner Link al commento Condividi su altri siti More sharing options...
Chibi Goku Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 Non ricordo più molto di Java, quindi non mi ricordo se abbia o meno il concetto di format string o una cosa del genere, nè in che modo stampi un numero reale come default. Il tuo problema è che non arrotonda solo per quella particolare somma (o sottrazione) verso un più leggibile 6.86, oppure non ti gusta che il risultato appaia "sbagliato" leggendo tutti i decimali? Direi che il problema è che dovrebbe uscire 16.86 ^^ E' il motivo per cui l'operatore "uguaglianza" fra due real non si deve usare mai, ma va sostituito da una sottrazione seguita dal confronto con un epsilon scelto sufficientemente piccolo a seconda dell'applicazione... Ah, il metodo di arrotondamento indicato nel link di formatted_brain può anche funzionare, ma sicuramente è lento come la fame e non usabile per altro che l'output a schermo (e anche in quel caso, devono di certo esserci sistemi migliori) Ok, la prima cosa la diamo per buona, direi che chi ha un po' di esperienza già lo sa, però quel risultato lì è sbagliato veramente di tanto =_= Link al commento Condividi su altri siti More sharing options...
werner Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 Non ricordo più molto di Java, quindi non mi ricordo se abbia o meno il concetto di format string o una cosa del genere, nè in che modo stampi un numero reale come default. Il tuo problema è che non arrotonda solo per quella particolare somma (o sottrazione) verso un più leggibile 6.86, oppure non ti gusta che il risultato appaia "sbagliato" leggendo tutti i decimali? Direi che il problema è che dovrebbe uscire 16.86 ^^ Secondo me ha sbagliato a trascrivere il codice, 20 è citato solo lì dentro, da tutte le altre parti (incluso il testo subito sotto il codice) sirtao dice 10 :) Link al commento Condividi su altri siti More sharing options...
sirtao Inviato 23 Novembre, 2009 Autore Share Inviato 23 Novembre, 2009 si, ho sbagliato a copiare una delle varie prove con valori diversi per vedere se faceva sempre quell'errore(ora ho corretto il code)... ma comunque e' un errorone. francamente, mi par strano che una semplice sottrazione finisca con un errore del genere... cioe', non sono un ingegniere, ma un errore del genere io lo vedo come da uccidere i debugger maledendoli fino alla 10-3.14ima generazione.... Link al commento Condividi su altri siti More sharing options...
werner Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 (modificato) francamente, mi par strano che una semplice sottrazione finisca con un errore del genere... cioe', non sono un ingegniere, ma un errore del genere io lo vedo come da uccidere i debugger maledendoli fino alla 10-3.14ima generazione.... Invece è normalissimo, fidati E' che ormai la gente si fida così tanto dei computer che non te lo insegnano più se non all'università. A me l'hanno spiegato in prima liceo, ma il mio prof di informatica era un figo ^^ Il problema è che i numeri floating point non hanno nessuna corrispondenza diretta con l'aritmetica decimale: sono dei numeri in notazione scientifica in base due, a dimensione fissa. Fissa e non molto generosa, in singola precisione: un float a 32 bit ne dedica 8 all'esponente (da 2^-128 a 2^+127), uno al segno e i restanti 23 alla mantissa, cioè alle cifre significative. 23 cifre binarie (più una in realtà, recuperata rinormalizzando l'esponente, ma questo è un dettaglio) corrispondono a 7 cifre decimali. Dunque puoi scrivere all'incirca tutti i numeri del tipo A,BCDEFG x 10^N, con N compreso tra -37 e +37. Ne segue che un miliardo più tre, in singola precisione, fa.... un miliardo. (1,000000 x 10^9 + 3,000000 x 10^0 in sette cifre non ci sta....) Ti sembra che faccia schifo? Sì, in effetti lo fa; i single precision sono sempre stati un tipo di dato un po' del menga. Non per caso il "mio" vecchio, carissimo Turbo Pascal 7 usava dei "real" da 48 bit E adesso, con l'esuberanza di memoria che c'è, credo che si tenda quasi sempre a usare direttamente i double precision e via. Con i double non hai quasi mai problemi di precisione (52 bit di mantissa = 16 cifre), ma ti resta un problema ineliminabile: l'arrotondamento dei risultati intermedi. Quando fai un'operazione, tutti i bit che non ci stanno nella mantissa devono essere troncati. E molti numeri che in decimale hanno una scrittura banale, in binario sono periodici. Dunque NON POSSONO essere rappresentati esattamente... ecco perchè prima ho scritto "all'incirca". Modificato 23 Novembre, 2009 da werner Link al commento Condividi su altri siti More sharing options...
sirtao Inviato 23 Novembre, 2009 Autore Share Inviato 23 Novembre, 2009 capito, la solita roba che avrebbe dovuto dirmi quella balorda della prof di Informatica, ma data la sua ignoranza non ha mai accennato. Dovro' farlo notare anche al corso, pero', visto che quindi questo tipo di problema potrebbe apparire spesso. ma comunque non capisco come questo problema possa applicarsi a una SOTTRAZIONE A DUE DECIMALI... Link al commento Condividi su altri siti More sharing options...
formatted_brain Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 Con i double non hai quasi mai problemi di precisione (52 bit di mantissa = 16 cifre), ma ti resta un problema ineliminabile: l'arrotondamento dei risultati intermedi.Quando fai un'operazione, tutti i bit che non ci stanno nella mantissa devono essere troncati. E molti numeri che in decimale hanno una scrittura banale, in binario sono periodici. Dunque NON POSSONO essere rappresentati esattamente... Geekismi a parte, quel codice ha un'utilità o è un semplice esercizio di programmazione? Perchè il risultato lo si arrotonda anche abbastanza facilmente, ma dipende da cosa ci devi fare (e sinceramente dubito che il problema si presenti SOLO con 10-3.14... Però che culo a beccarli così al primo colpo ) Link al commento Condividi su altri siti More sharing options...
sirtao Inviato 23 Novembre, 2009 Autore Share Inviato 23 Novembre, 2009 esercizio. Prima lezione di Java al corso che sto' frequentando. pero', appunto, voglio capire il come, senno' come faccio a sapere QUANDO arrotondare? Link al commento Condividi su altri siti More sharing options...
werner Inviato 23 Novembre, 2009 Share Inviato 23 Novembre, 2009 (modificato) ma comunque non capisco come questo problema possa applicarsi a una SOTTRAZIONE A DUE DECIMALI... Perchè quella sottrazione è a due decimali in... decimale, ma NON in binario Gli unici numeri razionali che NON sono periodici in binario sono quelli che corrispondono a una frazione del tipo a/2^b; nel tuo caso, 10 lo puoi scrivere in quel modo[*], ma 314/100 no: ecco dunque che 3,14 non può essere memorizzato perfettamente. Il vero problema è che tu stai chiedendo al computer più precisione di quella che hai bisogno, arrivando a superare quella che ti può dare: anche con un umilissimo float, l'errore se c'è si presenta al settimo decimale, con un double al quindicesimo. Tu hai davvero bisogno di così tanti decimali? Ne dubito. Ti sei accorto del problema perchè hai fatto stampare il risultato come 6.859999999999999, con SEDICI cifre. Se ne avessi chieste "solo" dodici, il numero sarebbe stato arrotondato e il computer ti avrebbe tranquillamente restituito 6,86. Quindi se fai dei calcoli semplici non ti devi preoccupare, basta scegliere un numero sensato di decimali nelle stampate a video. I guai seri possono arrivare se devi scrivere dei cicli che rimasticano milioni di volte gli stessi numeri floating point, dove gli errori potrebbero sommarsi fra loro a ogni giro. La soluzione a questo genere di problemi, se si presentano, non è affatto banale e va valutata caso per caso, con l'aiuto dei molti tomi di analisi numerica che sono stati scritti nel corso degli anni. Comunque non è frequentissimo nemmeno in ambito scientifico, quindi non credo che incontrerai situazioni simili, visto che per fare matematica userai probabilmente librerie scritte da altri che a queste grane ci hanno già pensato Ah, ultima cosa: tutto questo è il motivo per cui le applicazioni finanziarie NON usano numeri in virgola mobile, ma grossi interi a 64 bit. [*] Posso dirti al volo che quel numero sarà memorizzato in hardware come 8 x (1 + 1/4), dunque esponente 3, mantissa (1)010000000000..... (il primo 1 è sottinteso.) La miglior rappresentazione di 3,14 se la vuoi te la trovi da solo con questa applet :P http://www.ajdesigner.com/fl_ieee_754_word/ieee_32_bit_word.php Modificato 23 Novembre, 2009 da werner Link al commento Condividi su altri siti More sharing options...
sirtao Inviato 23 Novembre, 2009 Autore Share Inviato 23 Novembre, 2009 buono a sapersi(tutta roba che quella inutile della mia prof avrebbe dovuto cavar fuori al primo anno...) Link al commento Condividi su altri siti More sharing options...
Messaggi raccomandati
Crea un account o accedi per lasciare un commento
Devi essere un utente registrato per poter lasciare un commento
Crea un account
Iscriviti per un nuovo account nella nostra comunità. È facile!
Registra un nuovo accountAccedi
Sei già un account? Accedi da qui.
Accedi Ora