2012-07-17 18 views
57

Esempio:Perché la "f" è necessaria quando si dichiarano i float?

float timeRemaining = 0.58f; 

Perché la f è richiesto al fine del numero?

+4

Probab perché altrimenti sarebbe trattato come "doppio". –

+2

0.58 (senza il suffisso f) è un letterale di tipo double e non si può assegnare un valore double a un float, proprio come non si può assegnare un valore int a una stringa. Tuttavia, puoi assegnare un valore float a un double perché qui stai allargando (C# lo convertirà implicitamente per te, poiché nessuna precisione andrà persa). – davenewza

+0

possibile duplicato di [Perché dovremmo usare letterali in C#?] (Http://stackoverflow.com/questions/732770/why-should-we-use-literals-in-c) – adatapost

risposta

62

La vostra dichiarazione di un galleggiante contiene due parti:

  1. Si dichiara che la variabile timeRemaining è di tipo float.
  2. Assegna il valore 0.58 a questa variabile.

Il problema si verifica nella parte 2.

Il lato destro è considerato a sé stante. Secondo la specifica C#, un numero contenente un punto decimale che non ha un suffisso viene interpretato come double.

Quindi ora abbiamo un valore double che vogliamo assegnare a una variabile di tipo float. Per fare questo, ci deve essere una conversione implicita da double a float. Non esiste una tale conversione, perché è possibile (e in questo caso si) perdere le informazioni nella conversione.

La ragione è che il valore utilizzato dal compilatore non è realmente 0.58, ma il valore di virgola mobile più vicino a 0,58, che è 0,57999999999999978655962351581366 ... per double ed esattamente 0,579999946057796478271484375 per float.

In senso stretto, lo f non è richiesto. È possibile evitare di dover utilizzare il suffisso f colando il valore di un float:

float timeRemaining = (float)0.58; 
+4

Due domande, come sei arrivato al numero '0.579999946057796478271484375', e come funzionerà '(float) 0.58'? Prima hai detto che non c'è conversione, perché le informazioni potrebbero andare perse, allora come mai il cast funzionerà? – SexyBeast

+3

1. Ho usato il calcolatore di Windows, che utilizza fino a 34 cifre. 2. Ho detto che non c'è conversione * implicita *. Un cast è una conversione esplicita, quindi stai dicendo esplicitamente al compilatore che vuoi la conversione, e questo è permesso. –

+0

Interessante ... Spero che tu stia ancora monitorando questo post. Sono stato introdotto per i suffissi che hanno eseguito "m" in precedenza per il webcast che sto visualizzando. Come hai ottenuto la calcolatrice di Windows per visualizzare .58 come valore float? Ho provato un paio di pulsanti che sembravano forzare questo, ma no ... continuava a ricevere 0,58. Devo rispettare un uomo che conosce i suoi strumenti così bene ... – user1585204

31

Perché esistono diversi tipi numerici che il compilatore può utilizzare per rappresentare il valore 0.58: float, double e decimal. A meno che tu non stia bene con il compilatore sceglierne uno per te, devi disambigarlo.

La documentazione per double afferma che se non si specifica il tipo da soli il compilatore sceglie sempre double come il tipo di una vera letterale numerico:

Per impostazione predefinita, un vero e proprio letterale numerico sul lato destro della l'incarico dell'operatore viene considerato doppio. Tuttavia, se si desidera un numero intero da trattare come doppio, utilizzare il suffisso d o D.

Aggiungendo il suffisso f crea un float; il suffisso d crea un double; il suffisso m crea un decimal. Tutti questi funzionano anche in maiuscolo.

Tuttavia, questo non è ancora sufficiente a spiegare il motivo per cui questo non può essere compilato:

float timeRemaining = 0.58; 

la metà mancante della risposta è che la conversione dal double0.58 al floattimeRemaining perde potenzialmente informazioni, in modo che il il compilatore rifiuta di applicarlo implicitamente. Se aggiungi un cast esplicito, viene eseguita la conversione; se aggiungi il suffisso f, non sarà necessaria alcuna conversione. In entrambi i casi il codice verrà quindi compilato.

+0

ma come può essere un doppio o un decimale se la variabile è un float, mi manca qualcosa – Thomas

+0

@BlazArt Sì, la frase che afferma che il compilatore non tenta nemmeno di controllare il target di assegnazione. La ragione di ciò sarà sepolta nelle scelte progettuali fatte dal team del compilatore. Direi che è meglio essere espliciti di fronte alla possibile confusione, oppure è troppo costoso preoccuparsi di implementare invece di avere solo due regole, una per 'int' e una per' double'. –

+0

@BlazArt: ho appena finito di dare una risposta, per favore guarda di nuovo. – Jon

1

Il problema è che NET, al fine di consentire ad alcuni tipi di operazioni implicite da effettuare coinvolgendo float e double, necessaria specificare esplicitamente cosa dovrebbe accadere in tutti gli scenari che coinvolgono operandi misti oppure consentire conversioni implicite tra i tipi da eseguire solo in una direzione; Microsoft ha scelto di seguire la guida di Java nel consentire la direzione che occasionalmente favorisce la precisione, ma spesso sacrifica la correttezza e generalmente crea problemi.

In quasi tutti i casi, prendendo il valore double che è più vicina ad una particolare quantità numerica e assegnando ad un float produrrà il valore float che è più vicina alla stessa quantità. Ci sono alcuni casi d'angolo, come il valore 9,007,199,791,611,905; la migliore rappresentazione float sarebbe 9,007,200,328,482,816 (che è disattivata da 536,870,911), ma la migliore rappresentazione double (ad esempio 9,007,199,791,611,904) a float produce 9,007,199,254,740,992 (che è disattivata di 536,870,913). In generale, tuttavia, la conversione della migliore rappresentazione double di una certa quantità su float produce la migliore rappresentazione possibile di float o una di due rappresentazioni sostanzialmente uguali.

Si noti che questo comportamento desiderabile si applica anche agli estremi; ad esempio, la migliore rappresentazione float per la quantità 10^308 corrisponde alla rappresentazione float ottenuta convertendo la migliore rappresentazione double di tale quantità. Allo stesso modo, la migliore rappresentazione float di 10^309 corrisponde alla rappresentazione float ottenuta convertendo la migliore rappresentazione double di quella quantità.

Sfortunatamente, le conversioni nella direzione che non richiedono un cast esplicito sono raramente altrettanto accurate. La conversione della migliore rappresentazione float di un valore in double raramente produrrà qualcosa di particolarmente vicino alla migliore rappresentazione double di tale valore e in alcuni casi il risultato potrebbe essere disattivato di centinaia di ordini di grandezza (ad esempio la conversione della migliore rappresentazione float di 10^40 a double darà un valore che confronta maggiore della migliore double rappresentazione di 10^300.

Purtroppo, le regole di conversione sono quello che sono, quindi si ha a vivere con l'utilizzo typecasts sciocche e suffissi durante la conversione valori nel direzione "sicura", e fare attenzione alle tipect implicite nella direzione pericolosa che spesso produce risultati fasulli

Problemi correlati