Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Jan 2002
    Messaggi
    220

    Errore sullo 0 per i tipi double

    Le operazioni sulle costanti di tipo double scazzano di brutto allo 0... Mi spiegate perché su con un for decremento 10 di 0.1 quando arriviamo allo 0 scazza di brutto? Giá dopo pochi passi appaiono molti piú decimali del necessario e allo 0 appare un numero assurdo...

    codice:
    public class Main {
    	public static void main(String[] args) {
    		double i;
    		for(i=10; i>-10; i-=0.1){
    			System.out.println(i);
    		}
    	}
    }
    Il risultato in console é:

    Notare allo 0 la console mostra 1.8790524691780774E-14

    codice:
    10.0
    9.9
    9.8
    9.700000000000001
    9.600000000000001
    9.500000000000002
    9.400000000000002
    9.300000000000002
    9.200000000000003
    9.100000000000003
    9.000000000000004
    8.900000000000004
    8.800000000000004
    8.700000000000005
    8.600000000000005
    8.500000000000005
    8.400000000000006
    8.300000000000006
    8.200000000000006
    8.100000000000007
    8.000000000000007
    7.9000000000000075
    7.800000000000008
    7.700000000000008
    7.6000000000000085
    7.500000000000009
    7.400000000000009
    7.30000000000001
    7.20000000000001
    7.10000000000001
    7.000000000000011
    6.900000000000011
    6.800000000000011
    6.700000000000012
    6.600000000000012
    6.500000000000012
    6.400000000000013
    6.300000000000013
    6.2000000000000135
    6.100000000000014
    6.000000000000014
    5.900000000000015
    5.800000000000015
    5.700000000000015
    5.600000000000016
    5.500000000000016
    5.400000000000016
    5.300000000000017
    5.200000000000017
    5.100000000000017
    5.000000000000018
    4.900000000000018
    4.8000000000000185
    4.700000000000019
    4.600000000000019
    4.5000000000000195
    4.40000000000002
    4.30000000000002
    4.200000000000021
    4.100000000000021
    4.000000000000021
    3.9000000000000212
    3.800000000000021
    3.700000000000021
    3.600000000000021
    3.500000000000021
    3.400000000000021
    3.3000000000000207
    3.2000000000000206
    3.1000000000000205
    3.0000000000000204
    2.9000000000000203
    2.8000000000000203
    2.70000000000002
    2.60000000000002
    2.50000000000002
    2.40000000000002
    2.30000000000002
    2.2000000000000197
    2.1000000000000196
    2.0000000000000195
    1.9000000000000195
    1.8000000000000194
    1.7000000000000193
    1.6000000000000192
    1.500000000000019
    1.400000000000019
    1.300000000000019
    1.2000000000000188
    1.1000000000000187
    1.0000000000000187
    0.9000000000000187
    0.8000000000000187
    0.7000000000000187
    0.6000000000000187
    0.5000000000000188
    0.4000000000000188
    0.3000000000000188
    0.2000000000000188
    0.1000000000000188
    1.8790524691780774E-14
    -0.09999999999998122
    -0.19999999999998122
    -0.2999999999999812
    -0.39999999999998126
    -0.49999999999998124
    -0.5999999999999812
    -0.6999999999999812
    -0.7999999999999812
    -0.8999999999999811
    -0.9999999999999811
    -1.0999999999999812
    -1.1999999999999813
    -1.2999999999999814
    -1.3999999999999815
    -1.4999999999999816
    -1.5999999999999817
    -1.6999999999999817
    -1.7999999999999818
    -1.899999999999982
    -1.999999999999982
    -2.099999999999982
    -2.199999999999982
    -2.299999999999982
    -2.399999999999982
    -2.4999999999999822
    -2.5999999999999823
    -2.6999999999999824
    -2.7999999999999825
    -2.8999999999999826
    -2.9999999999999827
    -3.0999999999999828
    -3.199999999999983
    -3.299999999999983
    -3.399999999999983
    -3.499999999999983
    -3.599999999999983
    -3.6999999999999833
    -3.7999999999999834
    -3.8999999999999835
    -3.9999999999999836
    -4.099999999999984
    -4.199999999999983
    -4.299999999999983
    -4.399999999999983
    -4.499999999999982
    -4.599999999999982
    -4.6999999999999815
    -4.799999999999981
    -4.899999999999981
    -4.9999999999999805
    -5.09999999999998
    -5.19999999999998
    -5.299999999999979
    -5.399999999999979
    -5.499999999999979
    -5.599999999999978
    -5.699999999999978
    -5.799999999999978
    -5.899999999999977
    -5.999999999999977
    -6.0999999999999766
    -6.199999999999976
    -6.299999999999976
    -6.3999999999999755
    -6.499999999999975
    -6.599999999999975
    -6.699999999999974
    -6.799999999999974
    -6.899999999999974
    -6.999999999999973
    -7.099999999999973
    -7.199999999999973
    -7.299999999999972
    -7.399999999999972
    -7.499999999999972
    -7.599999999999971
    -7.699999999999971
    -7.7999999999999705
    -7.89999999999997
    -7.99999999999997
    -8.09999999999997
    -8.199999999999969
    -8.299999999999969
    -8.399999999999968
    -8.499999999999968
    -8.599999999999968
    -8.699999999999967
    -8.799999999999967
    -8.899999999999967
    -8.999999999999966
    -9.099999999999966
    -9.199999999999966
    -9.299999999999965
    -9.399999999999965
    -9.499999999999964
    -9.599999999999964
    -9.699999999999964
    -9.799999999999963
    -9.899999999999963
    -9.999999999999963

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472
    Leggi qui.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it
    Registrato dal
    Jan 2002
    Messaggi
    220
    Ho letto e devo dire che non avendo mai fatto matematica binaria al liceo scientifico e nemmeno all'universitá mi appare piuttosto difficile capirne le sfumature anche se mi pare di aver afferrato i concetti...

    Nonostante tutto ho proprio voglia di imparare...

    Nella pratica se avessi bisogno di un contatore posso tranquillamente evitare lo 0, arrotondare i double o magari usare la classe Double...

    Certo é che, se dovessi proprio usare un contatore che va inesorabilmente verso lo 0 decrementandosi di 0.1, tu che faresti?

  4. #4
    Originariamente inviato da bernabaus
    Certo é che, se dovessi proprio usare un contatore che va inesorabilmente verso lo 0 decrementandosi di 0.1, tu che faresti?
    arrotonderei!

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Solitamente, per "risolvere" questo problema si impone un epsilon adeguatamente piccolo da creare un intorno dello zero che possa essere considerato proprio zero.

    Partendo dal tuo esempio, tu decrementi una variabile di 0.1 ad ogni ciclo. Considerando che, quando questa variabile assumerà il valore 0.1, al passaggio successivo avrò come valore proprio lo 0.0, posso assumere che qualunque valore sia compreso in un intervallo tra -0.01 e +0.01 possa essere considerato come zero. Il mio epsilon, quindi, potrebbe benissimo essere 0.01. Detto questo, proviamo a implementare questa soluzione:

    codice:
    public class DecrementoDecimale {
       public static void main(String[] args) {
          double epsilon = 0.01d;
          double val = 10.0d;
          for(int i=0; i<200; i++) {
             System.out.println( isZero(val, epsilon) );
             val -= 0.1d;
          }
       }
    
       public static boolean isZero(double d, double epsilon) {
          return ((0-epsilon) <= d) && (d <= epsilon);
       }
    }
    La funzione "isZero" si occupa di controllare se il valore della variabile cade nell'intorno che noi consideriamo come zero.

    Se provi questo codice vedrai che verrà stampato "true" solo in corrispondenza dello "zero".

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    scusa e usare il metodo equals della classe Double?
    Io in genere per i tipi wrappati, a parte Integer, mi affido a quello della classe che mi sembra ben fatto (guardando anche il codice)
    RTFM Read That F*** Manual!!!

  7. #7
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da valia
    scusa e usare il metodo equals della classe Double?
    Io in genere per i tipi wrappati, a parte Integer, mi affido a quello della classe che mi sembra ben fatto (guardando anche il codice)
    Non ho capito... il metodo equals() della classe Double non risolve il problema delle approssimazioni successive dovute allo standard IEEE 754.

    codice:
    public class ZeroDouble {
       public static void main(String[] args) {
          Double d = 5.0d;
          for(int i=0; i<100; i++) {
             d = d - 0.1d;
             System.out.println(d + " --> " + d.equals(0.0d));
          }
       }
    }
    O forse mi sono perso qualcosa...


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  8. #8
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    mi riferivo per il confronto a zero e basta, non all'approssimazione
    RTFM Read That F*** Manual!!!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.