Domanda

Sto lavorando su un Java/Groovy programma.Ho una doppia variabile che contiene un numero che è stato digitato dall'utente.Quello che voglio sapere è quanti numeri digitato dall'utente a destra del separatore decimale.Qualcosa di simile a:

double num = 3.14
num.getPlaces() == 2

Naturalmente, non si può fare questo con un doppio visto che con IEEE floating points ed è tutto un ravvicinamento.

Supponendo che io non riesco a ottenere la stringa digitata dall'utente, ma solo l'accesso al doppio del valore è stato archiviato, c'è un modo posso scrub che il doppio se un BigDecimal o somesuch per ottenere il "vero" numero di cifre decimali?(Quando la doppia viene visualizzato sullo schermo, si ottiene a destra, quindi immagino ci sia un modo per almeno cerca di indovinare?)

È stato utile?

Soluzione

No, non è possibile ... perché ci sono un sacco di diverse stringhe l'utente potrebbe aver digitato che sarebbe tutto essere analizzato allo stesso valore.

Il numero "reale" è quasi certo di avere più cifre decimali rispetto l'utente ha digitato. Ad esempio, 3.14 è memorizzato come esattamente 3,140000000000000124344978758017532527446746826171875. Non credo che si desidera visualizzare che per l'utente.

Per rendere più chiaro il problema, non si può dire dal valore doppio se l'utente è entrato in realtà:

3.14
3.140
3.140000
3.14000000000000012434

Quei quattro corde saranno tutti vi darà lo stesso valore - che dovrebbe rendere evidente che non si può eventualmente tornare a ciò che l'utente ha digitato nel

.

Se a tutti è possibile, cambiare il codice di analisi e utilizzare BigDecimal tutto.

Altri suggerimenti

Hai ragione c'è qualcosa di strano con doppie, ciò che viene stampato non è la stessa come il contenuto della variabile.

per esempio:

groovy:000> "123.0001".toBigDecimal()
===> 123.0001
groovy:000> "123.0001".toDouble()
===> 123.0001
groovy:000> new BigDecimal("123.0001".toDouble())
===> 123.000100000000003319655661471188068389892578125

Notare il danno è fatto nella conversione della stringa in un valore double, non quando il doppio è passata in un BigDecimal.Nutrire il doppio per il BigDecimal solo fornisce un modo semplice per vedere che cosa è in realtà il doppio, perché toString sta mentendo a voi.

Come Jon Skeet punti, la precisione non è un'opzione qui.Tuttavia, supponendo che il valore stampato sullo schermo è il risultato della chiamata toString il doppio, si dovrebbe essere in grado di ottenere un bigDecimal che non è più sbagliato il metodo toString versione del doppio, come questo:

groovy:000> d = "123.0001".toDouble()
===> 123.0001
groovy:000> d.toString()
===> 123.0001
groovy:000> new BigDecimal(d.toString())
===> 123.0001

Quindi non c'è bisogno di coinvolgere il BigDecimal, davvero, si può solo fare qualcosa di simile

groovy:000> d = 123.0001
===> 123.0001
groovy:000> s = d.toString()
===> 123.0001
groovy:000> s.substring(s.indexOf('.')).length() - 1
===> 4

Scusa per invalidare il tuo commento modificando.

BTW ecco, qualcosa di simile a Steve risposta, tradotta in groovy.(Ho preso il test per il punto decimale non trovato, perché se si esegue questa operazione su una macchina con localizzazioni incasinato così non è, utilizzando un punto per il punto decimale preferisco farlo saltare in aria di ritorno 0)

def getPlaces(d) {
    s = d.toString()
    s.substring(s.indexOf(".")).length() - 1
}

Sì, è possibile. Almeno se non ti dispiace che a volte si trova un risultato sbagliato. Dobbiamo assumere che l'utente è pigro ed è entrato non più di ~ 12 cifre decimali significative.

Quindi fare quanto segue:

  • Crea un BigDecimal con la doppia data nel costruttore. Che converte il doppio in una rappresentazione decimale esatto.

  • Prendi solo la frazione.

  • Get BigDecimal.toString () e trovare tre o più consecutivi '0' o cifre '9'.

  • Tagliare la frazione in onore di tre cifre. Se le cifre sono nove, aggiungere un "1" fine. Dopo che rimuovere tutti zeri finali.

  • Contare le cifre decimali rimanenti

Attenzione:. Questo può essere un po 'lento

Se si desidera solo il numero di bit significativi nel doppio si possono ottenere molto più veloce e più facile, ma decimal-> conversione binaria utilizza purtroppo quasi tutti i pezzi.

Se è assolutamente necessario prendere una doppia, e non dispiacerebbe avere un po 'di metodo di utilità per eseguirlo tramite, si potrebbe scrivere qualcosa di simile. Hai detto che non si ha accesso al valore stringa di ciò che l'utente è entrato, ma c'è un motivo per cui non è possibile convertire in una stringa e fare qualcosa di simile?

static int getPlaces(double num) {
    String numString = String.valueOf(num);

    return numString.indexOf(".0")==numString.length()-2?0:numString.length()-numString.indexOf(".")-1;
}

dunque, al posto del tuo esempio

 num.getPlaces() == 2

Si può fare

 getplaces(num) == 2

Spero che questo aiuti ..

Update, dato il vostro commento That the user entered. Good point.

Se l'utente ha inserito quello che appare come un intero (per esempio, 5) senza un punto decimale, e si sta ricevendo come un doppio, allora quello che si vuole ottenere è qualcosa di diverso da ciò che l'utente è entrato - per s / he avrà entrato 5, ma avrai ricevuto 5.0. Avresti alcun modo di sapere se l'utente è entrato in realtà 5 o 5.0.

se sei bloccato con un doppio, convertire in una stringa e contare il numero di caratteri dopo il punto decimale. Penso che ci sia qualcosa di magico coinvolti che visualizza i numeri come 1,99999999998 come "2"

quindi se si tratta di un valore immesso dall'utente. Accettare il valore come una stringa. Quindi è possibile utilizzare funzioni di stringa per trovare la posizione del "". e quindi sottrarre quel numero dalla lunghezza della stringa per ottenere il numero vostro ricerca. Naturalmente si vorrà trim (), e verificare che sia in realtà un numero che è stato immesso ..

Converti in BigDecimal. BigDecimal.scale () = numero di posti

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top