2010-04-07 6 views
9

Un modo intelligente per convertire un float come questo:C# galleggiante alla conversione decimale

float f = 711989.98f; 

in un decimale (o doppio), senza perdere di precisione?

ho provato:

decimal d = (decimal)f; 
decimal d1 = (decimal)(Math.Round(f,2)); 
decimal d2 = Convert.ToDecimal(f); 
+0

Maggiori dettagli: sto interfacciamento con un vecchio webservice che invia questo enorme oggetto che ha alcuni campi come galleggiante. Quando faccio la conversione in kaboom decimale ... non più soldi! – Adrian4B

+0

se questo proviene da un servizio web sul cavo è probabilmente XML, il che significa che non ci sono fluttuazioni o decimali, solo stringhe. Guarda dove queste stringhe sono convertite in formato "interno" – mfeingold

risposta

11

È troppo tardi, l'ottava cifra è stata persa nel compilatore. Il tipo float può memorizzare solo 7 cifre significative. Dovrai riscrivere il codice, l'assegnazione al doppio o al decimale ovviamente risolverà il problema.

+0

grazie Ho cambiato il tipo del campo sull'oggetto mappato da float in decimale e risolto il problema di conversione che stava accadendo durante la deserializzazione. – Adrian4B

1

hai provato?

decimal.TryParse() 

http://forums.asp.net/t/1161880.aspx

ci sono conversioni implicite tra float/double e decimale. Le conversioni numeriche implicite sono sempre garantite senza perdita di precisione o magnitudo e non causano eccezioni.

+1

Le conversioni implicite non sono garantite senza perdita di precisione. La conversione di '9007199791611905' in' double' produrrà '9007199791611904'. Convertire direttamente in 'float' produrrà' 9007200328482816'. La conversione in 'double' e quindi in' float' produrrà '9007199254740992' (che è più alto di se il numero è stato convertito direttamente in' float'). Inoltre, mentre i compilatori consentono la conversione implicita da 'float' a' double', tali conversioni hanno molte più probabilità di essere errate rispetto alle conversioni da 'double' a' float' che non sono consentiti ma dovrebbero esserlo. – supercat

+1

apparentemente @supercat [puoi convertire senza perdita 'float' in' double'] (http://stackoverflow.com/q/40550861/24874). Tuttavia è probabile che la conversione di 'double' in' float' introduca errori, a seconda dello specifico valore 'double' in questione. –

+0

@DrewNoakes: se uno ha usato un calcolo iterativo per calcolare la posizione di un oggetto usando type 'double', e poi desidera disegnarlo usando le routine grafiche che accettano' float', la conversione in 'float' ridurrebbe la precisione che sarebbe in genere inutile anche se conservato; sminuire la precisione sarebbe quasi certamente coerente con l'intento del programmatore. Al contrario, se alcuni codici, ad es.divide un 'int' o' long' da un 'float' e memorizza il risultato in un' double', quindi a meno che il programmatore non esegua esplicitamente il risultato della divisione su 'float' non presumerei che il programmatore ... – supercat

1

Hai perso precisione nel momento in cui hai scritto 711989.98f.

711989.98 è decimale. Con f alla fine stai chiedendo al compilatore di convertirlo in float. Questa conversione non può essere eseguita senza perdere precisione.

Ciò che si desidera è decimale d = 711989.98m. Questo non perderà la precisione.

+0

Il tuo esempio usa solo un doppio, giusto? Potrebbe ancora perdere precisione per un numero diverso. Basta mettere una 'm' alla fine e rendere il letterale un decimale per iniziare. –

1

Questo potrebbe essere un errore del compilatore perché sembra che un float valido debba convertire direttamente in un decimale. ma non senza perdere risoluzione. La conversione di 125.609375 da virgola mobile in decimale perderà la risoluzione. Tuttavia, la conversione da float in double e poi double in decimal manterrà la risoluzione.

float float_val = 125.609375f; 

    decimal bad_decimal_val = (decimal)float_val; //125.6094 

    double double_val = (double)float_val; 
    decimal good_decimal_val = (decimal)double_val;