Java: come impostare la precisione per il doppio valore?

Stavo lavorando con i numeri di recente e ho avuto una situazione in cui voglio impostare la precisione di un valore doppio dire a 6 cifre o 4 cifre, a seconda del valore memorizzato nel database.

Ad esempio, se nel database la precisione è impostata su 4 cifre, l’output deve apparire come,

10.0000 .

Ho provato con DecimalFormat e usando la stringa ##.#### , ma è fastidioso usare i simboli ogni volta.

C’è un approccio migliore, dì qualcosa di simile qui sotto:

 Double value = 10.0; value.setPrecision(4); 

Non è ansible impostare la precisione di un doppio (o doppio) su un numero specificato di cifre decimali, poiché i valori a virgola mobile non hanno cifre decimali. Hanno cifre binarie.

Dovrai convertire in un decimale decimale, tramite BigDecimal o DecimalFormat , a seconda di cosa vuoi fare con il valore successivo.

Vedi anche la mia risposta a questa domanda per una confutazione delle inevitabili * 100/100 risposte.

Puoi provare BigDecimal per questo scopo

 Double toBeTruncated = new Double("3.5789055"); Double truncatedDouble = BigDecimal.valueOf(toBeTruncated) .setScale(3, RoundingMode.HALF_UP) .doubleValue(); 

questo è un modo semplice per farlo.

 String formato = String.format("%.2f"); 

imposta la preselezione a 2 cifre o qualsiasi.

se vuoi solo stamparlo, usa questo modo.

 System.out.printf("%.2f",123.234); 

Per impostare la precisione per i doppi valori, DecimalFormat è una buona tecnica. Per utilizzare questa class, importare java.text.DecimalFormat e creare l’object ad esempio

 double no=12.786; DecimalFormat dec = new DecimalFormat("#0.00"); System.out.println(dec.format(no)); 

Quindi stamperà due cifre dopo il punto decimale qui stamperà 12.79

Questo ha funzionato per me:

 public static void main(String[] s) { Double d = Math.PI; d = Double.parseDouble(String.format("%.3f", d)); // can be required precision System.out.println(d); } 

La precisione di double e float è determinata dalle loro dimensioni e dal modo in cui vengono implementati i tipi di virgola mobile IEEE .

Il numero di cifre decimali nell’output, d’altra parte, è una questione di formattazione. Hai ragione a dire che digitare continuamente la stessa costante è una ctriggers idea. Dovresti invece dichiarare una stringa costante e usare la sua rappresentazione simbolica.

 private static final String DBL_FMT = "##.####"; 

L’utilizzo di una rappresentazione simbolica ti consente di modificare la precisione in tutti i punti in cui la costante viene utilizzata senza cercare nel codice.

Ecco un modo efficace per raggiungere il risultato con due avvertimenti.

  1. Limita la precisione alle cifre N ‘massime’ (non fissate su N cifre).
  2. Arrotonda il numero (non arrotondato al più vicino).

Vedi esempi di casi di test qui.

 123.12345678 ==> 123.123 1.230000 ==> 1.23 1.1 ==> 1.1 1 ==> 1.0 0.000 ==> 0.0 0.00 ==> 0.0 0.4 ==> 0.4 0 ==> 0.0 1.4999 ==> 1.499 1.4995 ==> 1.499 1.4994 ==> 1.499 

Ecco il codice. Le due avvertenze che ho menzionato sopra possono essere affrontate abbastanza facilmente, tuttavia, la velocità per me era più importante della precisione, quindi l’ho lasciata qui. Manipolazioni di stringhe come System.out.printf("%.2f",123.234); sono computazionalmente costosi rispetto alle operazioni matematiche. Nei miei test, il codice seguente (senza il sysout) impiegava 1/30 del tempo rispetto alle manipolazioni di String.

 public double limitPrecision(String dblAsString, int maxDigitsAfterDecimal) { int multiplier = (int) Math.pow(10, maxDigitsAfterDecimal); double truncated = (double) ((long) ((Double.parseDouble(dblAsString)) * multiplier)) / multiplier; System.out.println(dblAsString + " ==> " + truncated); return truncated; } 
 BigDecimal value = new BigDecimal(10.0000); value.setScale(4); 

Per espandersi su @EJP, il concetto di ‘precisione’ quando si ha a che fare con il doppio è estremamente difficile. Come discusso in https://stackoverflow.com/a/3730040/390153, non puoi nemmeno rappresentare 0.1 come un doppio indipendentemente dalla precisione, per lo stesso motivo non puoi rappresentare 1/3 in base 10 con precisione finita.

È necessario considerare il problema che si sta tentando di risolvere e prendere in considerazione:

a) Dovrei usare il doppio, in primo luogo; se la precisione è un concetto rilevante, allora usare il doppio potrebbe essere un errore.

b) Se i doppi sono appropriati, cosa intendo per precisione? Se si sta parlando solo di display, avvolgere la logica in una funzione di visualizzazione e sarà necessario gestirla solo in un unico punto; vale a dire. applica il principio ASCIUTTA.

Ho visto la risposta in cima:

 Double toBeTruncated = new Double("3.5789055"); Double truncatedDouble = BigDecimal.valueOf(toBeTruncated) .setScale(3, RoundingMode.HALF_UP) .doubleValue(); 

che penso non sia la risposta perfetta Perché la risposta cambierà quando si chiama .doubleValue () in molti casi. Esempio: output di BigDecimal.valueOf (toBeTruncated) .setScale (3, RoundingMode.HALF_UP) è 12.500

quindi dopo .doubleValue (), l’output sarà 12.5 ovvero la precisione viene persa.

La soluzione utilizza il tipo BigDecimal senza il metodo .doubleValue () per visualizzare o utilizzare la formattazione della stringa dopo la risposta finale

Forse questo metodo ti aiuterebbe a valutare i doppi valori.

 double truncate(double number) { int integerPart = (int) number; double fractionalPart = number - integerPart; fractionalPart *= 100; //It is for upto two decimal values after point. //You can increase the zeros to fulfill your needs. int fractPart = (int) fractionalPart; fractionalPart = (double) (integerPart) + (double) (fractPart)/100; return fractionalPart; } 

Questo metodo consentirà di impostare il livello di precisione.

 double truncate(double number, int precision) { double prec = Math.pow(10, precision); int integerPart = (int) number; double fractionalPart = number - integerPart; fractionalPart *= prec; int fractPart = (int) fractionalPart; fractionalPart = (double) (integerPart) + (double) (fractPart)/prec; return fractionalPart; } 
 public static String setPrecision(String number, int decimal) { double nbr = Double.valueOf(number); int integer_Part = (int) nbr; double float_Part = nbr - integer_Part; int floating_point = (int) (Math.pow(10, decimal) * float_Part); String final_nbr = String.valueOf(integer_Part) + "." + String.valueOf(floating_point); return final_nbr; }