Perché è necessario specificare un suffisso f
in un valore letterale float?
Perché altrimenti il valore predefinito è double
, che è un tipo di virgola mobile più comunemente usato rispetto al float
.
Dalla specifica del linguaggio Java, sezione 3.10.2 :
Un letterale a virgola mobile è di tipo float se è suffisso con una lettera ASCII F o f; altrimenti il suo tipo è doppio e può opzionalmente essere suffisso con una lettera ASC o D (§4.2.3).
(Personalmente preferirei che non ci fossero impostazioni predefinite, per chiarire in tutti i casi, ma è diverso.)
Poiché i valori letterali in virgola mobile non confiscati sono doppi e l’arrotondamento significa che anche i letterali di piccole dimensioni possono assumere valori diversi quando vengono arrotondati per virare e raddoppiare. Questo può essere osservato nel seguente esempio:
float f = (float) 0.67; if(f == 0.67) System.out.print("yes"); else System.out.print("no");
Questo produrrà no
, perché 0.67 ha un valore diverso quando viene arrotondato a float di quanto non lo sia quando è arrotondato al doppio. D’altra parte:
float f = (float) 0.67; if(f == 0.67f) System.out.print("yes"); else System.out.print("no");
… emette yes
.
MODIFICARE
Secondo esempio:
if(0.67 == 0.67f) System.out.print("Equal"); else System.out.print("Not Equal");
Esistono due tipi di virgola mobile che possono essere rappresentati come ad esempio 100.0
. Solo uno potrebbe essere l’impostazione predefinita. A causa della sua precisione limitata, float è un tipo estremamente specializzato. Il caso normale è doppio, quindi è il valore predefinito appropriato.
Sui processori moderni, float e double hanno prestazioni di calcolo simili. L’unico caso per usare float è array di grandi dimensioni in situazioni critiche per le prestazioni che richiedono una precisione limitata. L’utilizzo di float raddoppia il numero di valori in virgola mobile che si adattano a una riga della cache. Anche allora, capire se il float dà una precisione sufficiente per un dato calcolo è raramente banale.