Float e doppio tipo di dati in Java


220

Il tipo di dati float è un virgola mobile IEEE 754 a 32 bit a precisione singola e il doppio tipo di dati è un virgola mobile IEEE 754 a 64 bit a precisione doppia.

Cosa significa? E quando dovrei usare float invece di double o viceversa?


8
È necessario utilizzare float anziché double quando l'utilizzo della memoria è fondamentale. Se hai bisogno di calcoli più precisi, usa i doppi.
Everv0id

12
@ Everv0id: non sono sicuro di alcuna situazione in cui la memoria fosse così stretta che bisogna sacrificare la precisione per lo spazio. (Stai usando Java , per l'amor del cielo ...) Potrebbero esserci alcune situazioni in cui è richiesto, ma nella mia pratica l'ho visto molto di rado. Se volessi approfondire il motivo per cui ritieni che questa sia una buona idea, fornire una risposta con un esempio sarebbe un'aggiunta degna.
Makoto,


5
@Makoto in realtà, non ho mai usato float, solo doppi. Ma potrebbero esserci applicazioni (in teoria) che dovrebbero mantenere grandi quantità di numeri in virgola mobile, quindi l'utilizzo della memoria 2x potrebbe essere critico. In teoria, spesso; in pratica puoi sempre comprare ancora un altro server .
Everv0id

3
Ho usato numeri di precisione fissa a 4 byte e persino a 2 byte per risparmiare memoria, ma a meno che tu non ne abbia miliardi, è improbabile che ne valga la pena. Il tempo impiegato per scrivere "double" invece di "float" (ha una lettera in più) vale 1000 volte più della memoria aggiuntiva che usi, ma se usare doubleinvece di floatsalvarti da un bug di precisione, ne vale la pena .
Peter Lawrey,

Risposte:


259

La pagina Wikipedia su di essa è un buon punto di partenza.

Per riassumere:

  • floatè rappresentato in 32 bit, con 1 bit di segno, 8 bit di esponente e 23 bit del significato (o quanto segue da un numero di notazione scientifica: 2.33728 * 10 12 ; 33728 è il significato).

  • double è rappresentato in 64 bit, con 1 bit di segno, 11 bit di esponente e 52 bit di significato.

Per impostazione predefinita, Java utilizza doubleper rappresentare i suoi numeri in virgola mobile (quindi 3.14viene digitato un letterale double). È anche il tipo di dati che ti fornirà un intervallo di numeri molto più ampio, quindi ne incoraggio fortemente l'uso float.

Ci possono essere alcune librerie che in realtà costringono l'uso di float, ma in generale - a meno che non si può garantire che il vostro risultato sarà abbastanza piccolo da stare in float's campo prescritto , allora è meglio optare con double.

Se hai bisogno di precisione - ad esempio, non puoi avere un valore decimale che è inaccurato (come 1/10 + 2/10), o stai facendo qualcosa con la valuta (ad esempio, che rappresenta $ 10,33 nel sistema), quindi usa a BigDecimal, che può supportare un quantità arbitraria di precisione e gestire situazioni del genere in modo elegante.


4
233728 == mantissa non è nell'esempio dato? Voglio dire, dove altro è memorizzata la parte intera?
JaLoveAst1k,

1
@ mathguy54: Nella notazione scientifica, 2 sarebbe l'intero intero e .33728 sarebbe la mantissa. Ecco un riferimento a questo.
Makoto,

5
Stavo cercando informazioni su float e doppi e ho trovato questo e dovevo commentare: se stai facendo qualcosa con una valuta che non comporta centesimi frazionari, usare BigDecimal è ridicolo. La valuta comune è costituita da dati discreti, pertanto è necessario utilizzare un tipo di dati intero. (Questo è uno degli errori più comuni commessi dai giovani programmatori - poiché usiamo un. Per separare i dollari dai centesimi, pensano che sia un valore in virgola mobile. Non lo è.)
Trixie Wolf

2
@TrixieWolf, potresti essere più specifico, hai proposto di usare due numeri interi (parti intere e decimali)? E stai parlando di valuta comune, e il resto? Alcuni importi sono valutati con 6 decimali, quindi non puoi semplicemente *100. Per favore, hai un punto qui, ma potresti essere più preciso :)
AxelH,

9
@AxelH Ad eccezione dei medi dei calcoli finanziari in cui possono esistere centesimi frazionari, il denaro è sempre discreto. Dovresti usare un tipo intero per memorizzare i dati. Quindi $ 5,34 verrebbero memorizzati come 534. La porzione in dollari è val / 100 in matematica dei numeri interi, e i centesimi sono val% 100 in matematica dei numeri interi, dove% si riferisce all'operazione rimanente. Per denaro con più posizioni oltre il decimale dovrebbe essere comunque memorizzato come integrale perché è discreto. Anche se non è discreto, spesso vorrai tornare a una memoria discreta per la maggior parte del tempo perché è preciso in modo da non perdere soldi per arrotondare gli errori.
Trixie Wolf,

72

Un galleggiante ti dà ca. 6-7 precisione delle cifre decimali mentre una doppia ti dà ca. 15-16. Anche l'intervallo di numeri è maggiore per il doppio.

Un doppio necessita di 8 byte di spazio di archiviazione mentre un float richiede solo 4 byte.


13

I numeri a virgola mobile, noti anche come numeri reali, vengono utilizzati per valutare espressioni che richiedono precisione frazionaria. Ad esempio, calcoli come radice quadrata o trascendentali come seno e coseno, danno come risultato un valore la cui precisione richiede un tipo a virgola mobile. Java implementa il set standard (IEEE – 754) di tipi e operatori in virgola mobile. Esistono due tipi di tipi a virgola mobile, float e double, che rappresentano rispettivamente numeri a precisione singola e doppia. La loro larghezza e intervalli sono mostrati qui:


   Name     Width in Bits   Range 
    double  64              1 .7e308 to 1.7e+308
    float   32              3 .4e038 to 3.4e+038


galleggiante

Il tipo float specifica un valore a precisione singola che utilizza 32 bit di memoria. La precisione singola è più veloce su alcuni processori e occupa metà dello spazio rispetto alla doppia precisione, ma diventerà imprecisa quando i valori sono molto grandi o molto piccoli. Le variabili di tipo float sono utili quando è necessario un componente frazionario, ma non richiedono un elevato grado di precisione.

Ecco alcune dichiarazioni di variabili float di esempio:

float hightemp, lowtemp;


Doppio

La doppia precisione, indicata dalla doppia parola chiave, utilizza 64 bit per memorizzare un valore. La doppia precisione è in realtà più rapida della singola precisione su alcuni processori moderni che sono stati ottimizzati per i calcoli matematici ad alta velocità. Tutte le funzioni matematiche trascendentali, come sin (), cos () e sqrt (), restituiscono valori doppi. Quando è necessario mantenere la precisione su molti calcoli iterativi o manipolare numeri di grande valore, il doppio è la scelta migliore.


Questa risposta per chiarire chiaramente quando dovremmo usare float e double. Perché no?
Vinci il

8
Né i tipi floatdoublesono meglio utilizzati per la valuta in Java, perché aprono l'opportunità di errori di arrotondamento. Questo articolo è più dettagliato: javapractices.com/topic/TopicAction.do?Id=13
PPartisan

1
"Il float può essere utile quando si rappresentano dollari e centesimi." - No no no no no no no. Mai e poi mai conservare la valuta come float / double.
riduzione dell'attività

2

Java sembra avere comunque una propensione all'utilizzo del doppio per i calcoli:

Nel caso specifico del programma che ho scritto oggi, i metodi non funzionavano quando utilizzavo float, ma ora funzionano benissimo quando ho sostituito float con double (nell'IDE NetBeans):

package palettedos;
import java.util.*;

class Palettedos{
    private static Scanner Z = new Scanner(System.in);
    public static final double pi = 3.142;

    public static void main(String[]args){
        Palettedos A = new Palettedos();
        System.out.println("Enter the base and height of the triangle respectively");
        int base = Z.nextInt();
        int height = Z.nextInt();
        System.out.println("Enter the radius of the circle");
        int radius = Z.nextInt();
        System.out.println("Enter the length of the square");
        long length = Z.nextInt();
        double tArea = A.calculateArea(base, height);
        double cArea = A.calculateArea(radius);
        long sqArea = A.calculateArea(length);
        System.out.println("The area of the triangle is\t" + tArea);
        System.out.println("The area of the circle is\t" + cArea);
        System.out.println("The area of the square is\t" + sqArea);
    }

    double calculateArea(int base, int height){
        double triArea = 0.5*base*height;
        return triArea;
    }

    double calculateArea(int radius){
        double circArea = pi*radius*radius;
        return circArea;
    }

    long calculateArea(long length){
        long squaArea = length*length;
        return squaArea;
    }
}

Ho avuto lo stesso problema oggi. Quale può essere la ragione dietro questo pregiudizio?
Shachi,

2

Questo darà errore:

public class MyClass {
    public static void main(String args[]) {
        float a = 0.5;
    }
}

/MyClass.java:3: errore: tipi incompatibili: possibile conversione con perdita dal doppio al float float a = 0,5;

Funzionerà perfettamente

public class MyClass {
    public static void main(String args[]) {
        double a = 0.5;
    }
}

Funzionerà anche perfettamente

public class MyClass {
    public static void main(String args[]) {
        float a = (float)0.5;
    }
}

Motivo : Java per impostazione predefinita memorizza i numeri reali come doppio per garantire una maggiore precisione.

Il doppio occupa più spazio ma più preciso durante il calcolo e il float occupa meno spazio ma meno preciso.


1

Secondo gli standard IEEE, float è una rappresentazione a 32 bit di un numero reale mentre double è una rappresentazione a 64 bit.

Nei programmi Java normalmente vediamo principalmente l'uso del doppio tipo di dati. È solo per evitare overflow poiché l'intervallo di numeri che può essere ospitato utilizzando il doppio tipo di dati è maggiore dell'intervallo quando viene utilizzato il float.

Anche quando è richiesta un'elevata precisione, viene incoraggiato l'uso del doppio. Pochi metodi di libreria che sono stati implementati molto tempo fa richiede ancora l'uso del tipo di dati float come un must (questo è solo perché è stato implementato usando float, nient'altro!).

Ma se sei sicuro che il tuo programma richiede piccoli numeri e non si verificherà un overflow con l'uso di float, l'uso di float migliorerà notevolmente la complessità dello spazio poiché i float richiedono metà della memoria richiesta dal doppio.


0

Questo esempio illustra come estrarre il segno (il bit più a sinistra), l'esponente (gli 8 bit seguenti) e la mantissa (i 23 bit più a destra) da un float in Java.

int bits = Float.floatToIntBits(-0.005f);
int sign = bits >>> 31;
int exp = (bits >>> 23 & ((1 << 8) - 1)) - ((1 << 7) - 1);
int mantissa = bits & ((1 << 23) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Float.intBitsToFloat((sign << 31) | (exp + ((1 << 7) - 1)) << 23 | mantissa));

Lo stesso approccio può essere usato per i doppi (esponente a 11 bit e mantissa a 52 bit).

long bits = Double.doubleToLongBits(-0.005);
long sign = bits >>> 63;
long exp = (bits >>> 52 & ((1 << 11) - 1)) - ((1 << 10) - 1);
long mantissa = bits & ((1L << 52) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Double.longBitsToDouble((sign << 63) | (exp + ((1 << 10) - 1)) << 52 | mantissa));

Credito: http://sj.github.io/java-float/


0

Dovresti usare il doppio anziché il float per calcoli precisi e il float invece del doppio quando usi calcoli meno accurati. Float contiene solo numeri decimali, ma double contiene un numero in virgola mobile a precisione doppia IEEE754, che semplifica il contenimento e il calcolo dei numeri in modo più accurato. Spero che questo ti aiuti.


0

Nei normali calcoli di programmazione, non utilizziamo float. Se ci assicuriamo che l'intervallo di risultati rientri nell'intervallo del tipo di dati float, possiamo scegliere un tipo di dati float per il salvataggio della memoria. Generalmente, usiamo il doppio per due motivi:

  • Se si desidera utilizzare il numero in virgola mobile come tipo di dati float, il chiamante del metodo deve esplicitamente aggiungere il suffisso F o f, poiché per impostazione predefinita ogni numero in virgola mobile viene considerato doppio. Aumenta l'onere per il programmatore. Se utilizziamo un numero in virgola mobile come doppio tipo di dati, non è necessario aggiungere alcun suffisso.
  • Float è un tipo di dati a precisione singola che significa che occupa 4 byte. Quindi, nei calcoli di grandi dimensioni, non otterremo un risultato completo. Se scegliamo un doppio tipo di dati, occupa 8 byte e otterremo risultati completi.

Entrambi i tipi di dati float e double sono stati progettati appositamente per i calcoli scientifici, dove sono accettabili errori di approssimazione. Se l'accuratezza è la preoccupazione più importante, si consiglia di utilizzare la classe BigDecimal anziché i tipi float o double. Fonte: - Float e doppi tipi di dati in Java

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.