Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    doubleToVect (errore logica)

    Ciao a tutti,
    sto lavorando al mio primo progetto in java ma mi si presenta il problema in un algoritmo con il quale dovrei trasformare un double (es:1234.56) in un vettore di double sotto questa forma [0.06; 0.5; 4.0; 30.0; 200.0; 1000.0].
    Il metodo si prende il compito di togliere la virgola e di aggiungere uno zero finale nel caso il numero non arrivi alla seconda cifra decimale.
    Ovviamente il dominio della funzione è ogni double con 2 decimali dopo la virgola (infatti verrà utilizzato per fare operazioni coi soldi).
    Penso in ogni caso che non ci sia niente di più esaustivo del codice stesso:

    codice:
        public static double[] doubleToVect(double num) {
            
            /* Primo stadio: double */
            double dbl=num;
            
            /* Secondo stadio: stringa */
            String str = Double.toString(dbl);      // trasforma in stringa
            
            /*
             Se il numero è del tipo xy.z (un decimale dopo la virgola),
             lo rende nella forma xy.z0 con due decimali dopo la virgola.
             */
            if (str.charAt(str.length()-2)=='.') {
                str += "0";
            }
            
            
            /* Terzo stadio: vettore di double*/
            double [] vettDbl = new double[13];
            
            
            
            /* Elimino il punto(virgola) della stringa (ex double), concatenando due substring */
            str = str.substring(0,str.length()-3)        // parte intera (es: 123,45-->123)
                                   +
               str.substring(str.length()-2,str.length());  // parte decimale (es: 123,45-->45)
            
            /**
             * Scorre la stringa, trasforma il carattere corrente in intero e lo
             * aggiunge al vettore.
             * Inverte, inoltre, l'ordine dei numeri.
             */
            for(int i=1; i<=str.length();i++) {
                vettDbl[i-1] = str.charAt(str.length()-i)  -  (int)'0';
            }
            
            // ora il numero 1234.56 è nella forma [6.0; 5.0; 4.0; 3.0; 2.0; 1.0; 0.0; etc]
            
            /**
             * Scorre il vettore e trasforma il numero corrente al rispettivo numero
             * alla posizione propria (centesimi, decimi, unità, decine etc)
             */
            for(int i=0; i< vettDbl.length;i++) {
                vettDbl[i]=((int)vettDbl[i]) * Math.pow(10, -2+i);
            }
            
            // ora [6.0; 5.0; 4.0; 3.0; 2.0; 1.0] ---> [0.06; 0.5; 4; 30; 200; 1000]
            
            return vettDbl;
        }
    Il programma sembra funzionare alla perfezione infatti provandolo con il codice:

    codice:
            System.out.println("\n\n\n\n Prova del metodo doubleToVect()");
            System.out.println("Inserisci il valore del double che si vuole ottenere sotto forma di vettore");
            val = tastiera.nextDouble();
            double [] vett = new double[13];
            vett = Denaro.doubleToVect(val);
            for(int j=0; j< vett.length;j++) {
                System.out.print(vett[j]+" ");
            }
    Nella maggiorparte dei casi mi dà risultati corretti ma nel caso inserisca come valore d'ingresso numeri non interi mi trasforma i primo decimale (decimi) in una cosa senza (apparentemente) senso:
    Prova del metodo doubleToVect()
    Inserisci il valore del double che si vuole ottenere sotto forma di vettore
    1.3
    0.0 0.30000000000000004 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

    Prova del metodo doubleToVect()
    Inserisci il valore del double che si vuole ottenere sotto forma di vettore
    12345.67
    0.07 0.6000000000000001 5.0 40.0 300.0 2000.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0
    Ovviamente c'è un errore di logica ma dopo una notte passata in bianco e quasi mezzo litro di caffè ingerito chiedo aiuto

    Qualcuno riuscirebbe a spiegarmi che cosa sto sbagliando?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: doubleToVect (errore logica)

    Originariamente inviato da lomiz
    Ovviamente c'è un errore di logica
    Nessun errore di logica! Semplicemente questo è uno dei problemi che saltano fuori quando si usano i numeri floating-point.

    Dal punto di vista teorico, i numeri in virgola mobile consentono di rappresentare un sotto-insieme dei numeri reali. Questo vuol dire che non tutti i numeri reali possono essere rappresentati in un valore in virgola mobile memorizzato su un numero finito e limitato di bit.

    Per fare qualche esempio: su un numero limitato di bit (es. 32 bit o 64 bit come è tipico) il numero 0,75 può essere rappresentato in modo perfetto in virgola mobile mentre 0,8 non può essere rappresentato in modo perfetto (ci vorrebbe un numero teoricamente infinito di bit!), cioè non potrà essere veramente 0,8. Potrà essere un pochino di meno o un pochino di più (e questo pochino è veramente molto molto piccolo).

    A ciò si aggiunge il fatto che le operazioni matematiche, sia per fare i tuoi calcoli, sia per convertire il numero in stringa (perché anche qui si usano dei calcoli) possono portare a delle perdite di precisione.

    Se vuoi fare una cosa semplice, stampa il numero limitando il numero di cifre decimali (si può fare con un DecimalFormat o con il metodo printf/format).

    L'argomento su queste problematiche è molto vasto e comunque non sono il-guru-di-matematica-che-può-spiegartelo.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Più o meno penso di aver capito (anche se il mio 4 in matematica non mi dà di certo una mano).
    In pratica cio' che mi hai spiegato non è altro che un ragionamento derivato dal concetto di "limite".

    Ho googlato un po' e letto le api riguardo a DecimalFormat ma non riesco a capire come applicarlo al mio codice.
    In pratica tu dici che lo dovrei utilizzare prima di lavorare sulla stringa in questa (probabilmente sbagliata) maniera:
    codice:
    [...]
    DecimalFormat format = new DecimalFormat("0.00"); 
    /* Secondo stadio: stringa */
    String str = format.format(Double.parseDouble(dbl);      // trasforma in stringa
    Ed in questo caso non mi servirebbe aggiungere manualmente uno zero ai numeri con un solo decimale?

    Oppure lo devo applicare ad ogni elemento double del vettore finale, scorrendolo e "formattando" come da codice sopra riportato?

    Grazie per la pazienza =)

  4. #4

  5. #5
    Ok forse ho risolto modificando la riga
    codice:
    vettDbl[i]=((int)vettDbl[i]) * Math.pow(10, -2+i);
    in:
    codice:
    vettDbl[i]=Double.parseDouble( formato.format( ((int)vettDbl[i]) * Math.pow(10, -2+i) ) );
    Ci sono metodi migliori (magari più efficienti) per sfruttare il DecimalFormat o va bene così?

  6. #6
    up (scusate per l'insistenza ma da questo programma ne deriva un mio voto )

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.