2016-04-15 67 views
8

Ho il seguente doppio calcolo in Java:Java calcolo doppia perdere in precisione

double C1 = some value; // It's always an integer 
double C2 = some value; // It's always integer, and C2 >= C1 
double S = some value;  // It's always 0 < S <= 1 
double carry = some value; // It's always 0 <= carry < 1 

double rate = ((C1/C2)/S); 
double C3 = Math.floor((rate * S * C2) + carry); 

Ora, se non abbiamo perso la precisione, C3 == C1 sarebbe vero. Ma dal momento che perdiamo la precisione, sarà sempre C3 e C1 uguali?

Se non sarebbero sempre uguale, se ho C1, C2, S e C3, come potrei modificare il rate per assicurarsi che dopo il calcolo C3 sarebbe pari a C1?

Nota: sfortunatamente l'utilizzo di BigDecimal non è un'opzione.

+1

se siete interessati a mantenere la precisione poi fare usare un 'BigDecimal'. – SomeJavaGuy

+0

sfortunatamente usare BigDecimal non è un'opzione, dato che la velocità è già stata memorizzata dopo che la precisione è stata persa, e non posso fare nulla al riguardo. – user1819676

+7

@KevinEsche BigDecimal impedisce solo la perdita di precisione se i numeri sono tutti rappresentabili come frazioni decimali finali. Considera il caso di C1 = 1, C2 = 1, S = 0,3 –

risposta

3

Generalmente, non confrontiamo due valori doppi direttamente tramite ==. Invece, misuriamo la differenza tra loro. per esempio. Math.abs(C3 - C1) < 1e-6.

+0

Sì, se si trattava di confrontare i doppi. Ma la funzione che esegue Math.floor restituisce un intero. Guardate in questo modo. 'S' e' C2' sono memorizzati in db, e abbiamo quella funzione che in futuro verrà utilizzata per calcolare C3.Ora vogliamo memorizzare 'rate' o alcune modifiche di' rate' a db per garantire che la funzione generi 'C3 == C1' – user1819676

3

Non così.

Il punto in virgola mobile è un'approssimazione. Il doppio successivo, il bit 1 aggiunto alla mantissa può causare un gap piuttosto ampio per i grandi esponenti tra questi due doppi.

S approssimativo a 0 causerà enormi doppi, che hanno un grande divario tra di loro. Ciò non sarà più correggibile, ad esempio con quel semplice arrotondamento. Anche se la piccola S non causa che la divisione superi il doppio raggio con INFINITY.

si può facilmente essere di per 1000.