2015-11-23 9 views
32

Si prega di vedere il mio esempio qui sotto.Perché la conversione tra stringa e float è errata?

float maxFloat = float.MaxValue; 
string s = maxFloat.ToString(); 
float result = float.Parse(s); // same with Convert.ToSingle(s); 

bool mustEqual = (maxFloat == result); 
// It returns FALSE, why? 
+17

Dmitry ha la risposta, ma nota che confrontare i float per l'uguaglianza esatta è quasi sempre un errore: devi scegliere il tipo di precisione desiderato, assicurarti che rientri nelle capacità del tipo di dati specificato e fare il confronto solo per la precisione data. – Luaan

+16

@Luaan Non è un errore se ci si assicura che i viaggi di andata e ritorno non cambino il valore, che è una cosa valida da desiderare dalla serializzazione e deserializzazione. Anche se i calcoli successivi non sono esattamente prevedibili a causa dell'arrotondamento, non c'è motivo di accettare errori di arrotondamento su passi che possono essere esatti (come un float -> stringa -> float roundtrip). – delnan

+2

Il confronto dei valori in virgola mobile per l'uguaglianza è quasi * sempre * un *** *** ***. – RBarryYoung

risposta

47

Si dovrebbe usare "R" stringa di formato:

https://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx.

https://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx#RFormatString

"R" o "r" di andata e ritorno Risultato: una stringa che può andata e ritorno per un numero identico . Supportato da: Single, Double e BigInteger. Specificatore di precisione: ignorato.

float maxFloat = float.MaxValue; 
    string s = maxFloat.ToString("R"); // <- "R" 
    float result = float.Parse(s); 

    bool mustEqual = (maxFloat == result); 
+0

Aspetta, non significa che * non è * ufficialmente supportato da float? – deworde

+9

@deworde: 'float' e' Single' sono sinonimi: https://msdn.microsoft.com/en-US/library/b1e65aza.aspx (così come 'double' e' Double'). Msgstr "Tipo float ... .NET Framework type System.Single" –

29

// It returns FALSE, why?

Poiché float.ToString() uscita un numero di precisione 7 cifre per impostazione predefinita, in modo che il float.MaxValue che ha un valore di 3.40282347E+38 (precisione 9 cifre) diventerà arrotondato a 3.402823E+38 e il tuo controllo fallisce perché ovviamente lo 3.402823E+38 != 3.40282347E+38.

Se si specifica esplicitamente un identificatore di formato per produrre float.MaxValue con precisione a 9 cifre, ad es. float.MaxValue.ToString("G9"), l'assegno avrà successo.

Problemi correlati