Tipo de datos flotante y doble en Java

220

El tipo de datos flotantes es un punto flotante IEEE 754 de 32 bits de precisión simple y el tipo de datos doble es un punto flotante IEEE 754 de 64 bits de precisión doble.

Qué significa eso? ¿Y cuándo debo usar float en lugar de double o viceversa?

León
fuente
8
Debe usar flotantes en lugar de dobles cuando el uso de memoria es crítico. Si necesita cálculos más precisos, use dobles.
Everv0id
12
@ Everv0id: No estoy seguro de ninguna situación en la que la memoria sea tan escasa que haya que sacrificar la precisión por el espacio. (Estás utilizando Java , por amor de Dios ...) Puede haber algunas situaciones en las que se requiera, pero en mi práctica rara vez lo he visto. Si quisiera explicar por qué cree que es una buena idea, proporcionar una respuesta con, por ejemplo, sería una buena adición.
Makoto
55
@Makoto en realidad, nunca he usado carrozas, solo dobles. Pero podría haber aplicaciones (en teoría) que deberían mantener grandes cantidades de números de coma flotante, por lo que el uso de memoria 2x podría ser crítico. En teoría, ofc; en la práctica siempre puedes comprar otro servidor .
Everv0id
3
He usado números de precisión fijos de 4 bytes e incluso 2 bytes para ahorrar memoria, pero a menos que tenga miles de millones de estos, es poco probable que valga la pena. El tiempo que le lleva escribir "doble" en lugar de "flotante" (tiene una letra más) vale 1000 veces más que la memoria adicional que usa, pero si usa en doublelugar de floatsalvarlo de un error relacionado con la precisión, vale la pena .
Peter Lawrey

Respuestas:

259

La página de Wikipedia es un buen lugar para comenzar.

Para resumir:

  • floatse representa en 32 bits, con 1 bit de signo, 8 bits de exponente y 23 bits del significado (o lo que sigue de un número de notación científica: 2.33728 * 10 12 ; 33728 es el significado).

  • double se representa en 64 bits, con 1 bit de signo, 11 bits de exponente y 52 bits de significado.

Por defecto, Java utiliza doublepara representar sus números de punto flotante (por lo que 3.14se escribe un literal double). También es el tipo de datos que le dará un rango de números mucho mayor, por lo que recomendaría encarecidamente su uso float.

Puede haber ciertas bibliotecas que realmente fuerzan su uso float, pero en general, a menos que pueda garantizar que su resultado sea lo suficientemente pequeño como para caber en floatel rango prescrito , entonces es mejor optar pordouble .

Si necesita precisión, por ejemplo, no puede tener un valor decimal que sea inexacto (como 1/10 + 2/10), o está haciendo algo con moneda (por ejemplo, que representa $ 10.33 en el sistema), entonces use un BigDecimal, que puede admitir un cantidad arbitraria de precisión y maneja situaciones como esa con elegancia.

Makoto
fuente
44
¿No es 233728 == mantissa en el ejemplo dado? Quiero decir, ¿dónde más se almacena la parte entera?
JaLoveAst1k
1
@ mathguy54: En notación científica, 2 sería el entero entero y .33728 sería la mantisa. Aquí hay una referencia a eso.
Makoto
55
Estaba buscando información sobre flotadores y dobles y encontré esto y necesitaba comentar: si está haciendo algo con moneda que no implique centavos fraccionales, usar BigDecimal es ridículo. La moneda común son datos discretos, por lo que debe usar un tipo de datos entero. (Este es uno de los errores más comunes cometidos por los programadores jóvenes, ya que usamos a. Para separar dólares de centavos, piensan que es un valor de coma flotante. No lo es).
Trixie Wolf
2
@TrixieWolf, ¿podría ser más específico, propuso usar dos enteros (partes enteras y decimales)? Y estás hablando de la moneda común, ¿qué pasa con el resto? Algunas cantidades se evalúan con 6 decimales, por lo que no puede simplemente *100. Por favor, tiene un punto aquí, pero ¿podría ser más preciso? :)
AxelH
99
@AxelH Excepto por los medios de los cálculos financieros donde pueden existir centavos fraccionales, el dinero siempre es discreto. Usaría un tipo entero para almacenar los datos. Entonces, $ 5.34 se almacenarían como 534. La porción en dólares es val / 100 en matemática entera, y los centavos son val% 100 en matemática entera, donde% se refiere a la operación restante. Para dinero con más lugares más allá del decimal, aún debe almacenarse como integral porque es discreto. Incluso si no es discreto, a menudo querrá retroceder a un almacenamiento discreto la mayor parte del tiempo porque es preciso para que no pierda dinero por errores de redondeo.
Trixie Wolf
72

Un flotador te da aprox. Precisión de 6-7 dígitos decimales, mientras que un doble le da aprox. 15-16. Además, el rango de números es mayor para el doble.

Un doble necesita 8 bytes de espacio de almacenamiento, mientras que un flotante necesita solo 4 bytes.

Enrique
fuente
13

Los números de punto flotante, también conocidos como números reales, se usan al evaluar expresiones que requieren precisión fraccional. Por ejemplo, los cálculos como la raíz cuadrada o los trascendentales como el seno y el coseno, dan como resultado un valor cuya precisión requiere un tipo de punto flotante. Java implementa el conjunto estándar (IEEE – 754) de tipos y operadores de punto flotante. Hay dos tipos de tipos de coma flotante, flotante y doble, que representan números de precisión simple y doble, respectivamente. Su ancho y rangos se muestran aquí:


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


flotador

El tipo flotante especifica un valor de precisión simple que utiliza 32 bits de almacenamiento. La precisión simple es más rápida en algunos procesadores y ocupa la mitad de espacio que la precisión doble, pero se volverá imprecisa cuando los valores sean muy grandes o muy pequeños. Las variables de tipo flotante son útiles cuando necesita un componente fraccional, pero no requieren un alto grado de precisión.

Aquí hay algunos ejemplos de declaraciones de variables flotantes:

flotador hightemp, lowtemp;


doble

La precisión doble, como se indica con la palabra clave doble, utiliza 64 bits para almacenar un valor. La precisión doble es en realidad más rápida que la precisión simple en algunos procesadores modernos que han sido optimizados para cálculos matemáticos de alta velocidad. Todas las funciones matemáticas trascendentales, como sin (), cos () y sqrt (), devuelven valores dobles. Cuando necesita mantener la precisión en muchos cálculos iterativos, o está manipulando números de gran valor, el doble es la mejor opción.

Ye Win
fuente
Esta respuesta para aclarar claramente cuándo debemos usar flotador y doble. ¿Por qué no?
Ganaste el
8
Ni floattampoco doubletipos son los más utilizados para la moneda en Java, porque abren la posibilidad de errores de redondeo. Este artículo entra en más detalles: javapractices.com/topic/TopicAction.do?Id=13
PPartisan
1
"flotar puede ser útil cuando se representan dólares y centavos". - no no no no no NO NO. Nunca, nunca almacene la moneda como flotadores / dobles.
reducción de la actividad
2

Java parece tener un sesgo hacia el uso de doble para los cálculos, no obstante:

Por ejemplo, el programa que escribí hoy, los métodos no funcionaron cuando usé float, pero ahora funcionan muy bien cuando sustituí float con double (en el IDE de 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;
    }
}
Raymond Wachaga
fuente
Tuve el mismo problema hoy. ¿Cuál puede ser la razón detrás de este sesgo?
Shachi
2

Esto dará error:

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

/MyClass.java:3: error: tipos incompatibles: posible conversión con pérdida de doble a flotante flotante a = 0.5;

Esto funcionará perfectamente bien

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

Esto también funcionará perfectamente bien

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

Motivo : Java por defecto almacena números reales como el doble para garantizar una mayor precisión.

El doble ocupa más espacio pero es más preciso durante el cálculo y el flotante ocupa menos espacio pero es menos preciso.

Himanshu Singh
fuente
1

De acuerdo con los estándares IEEE, flotante es una representación de 32 bits de un número real, mientras que el doble es una representación de 64 bits.

En los programas de Java, normalmente vemos el uso del tipo de datos doble. Es solo para evitar desbordamientos, ya que el rango de números que pueden acomodarse usando el tipo de datos doble es mayor que el rango cuando se usa flotación.

Además, cuando se requiere alta precisión, se recomienda el uso de doble. Pocos métodos de biblioteca que se implementaron hace mucho tiempo aún requieren el uso del tipo de datos flotante como un deber (eso es solo porque se implementó usando flotante, ¡nada más!).

Pero si está seguro de que su programa requiere números pequeños y no se producirá un desbordamiento con el uso de float, entonces el uso de float mejorará en gran medida la complejidad de su espacio ya que los flotantes requieren la mitad de la memoria requerida por el doble.

Rubal
fuente
0

Este ejemplo ilustra cómo extraer el signo (el bit más a la izquierda), el exponente (los 8 bits siguientes) y la mantisa (los 23 bits más a la derecha) de un flotante en 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));

Se puede usar el mismo enfoque para dobles (exponente de 11 bits y mantisa de 52 bits).

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));

Crédito: http://sj.github.io/java-float/

acohen
fuente
0

Debería usar doble en lugar de flotante para cálculos precisos, y flotante en lugar de doble cuando use cálculos menos precisos. Flotante contiene solo números decimales, pero doble contiene un número de coma flotante de precisión doble IEEE754, lo que hace que sea más fácil contener y calcular números con mayor precisión. Espero que esto ayude.

boi yeet
fuente
0

En los cálculos regulares de programación, no usamos float. Si nos aseguramos de que el rango de resultados esté dentro del rango del tipo de datos flotantes, entonces podemos elegir un tipo de datos flotantes para guardar memoria. En general, usamos el doble por dos razones: -

  • Si queremos usar el número de punto flotante como tipo de datos flotantes, el método que llama debe sufijar explícitamente F o f, porque por defecto cada número de punto flotante se trata como doble. Aumenta la carga para el programador. Si usamos un número de coma flotante como tipo de datos doble, entonces no necesitamos agregar ningún sufijo.
  • El flotante es un tipo de datos de precisión simple, lo que significa que ocupa 4 bytes. Por lo tanto, en cálculos grandes, no obtendremos un resultado completo. Si elegimos el tipo de datos doble, ocupa 8 bytes y obtendremos resultados completos.

Los tipos de datos flotantes y dobles fueron diseñados especialmente para cálculos científicos, donde los errores de aproximación son aceptables. Si la preocupación principal es la precisión, se recomienda utilizar la clase BigDecimal en lugar de los tipos de datos flotantes o dobles. Fuente: - Tipos de datos flotantes y dobles en Java

Rocco Jerry
fuente