Java中的float和double数据类型


220

float数据类型是单精度32位IEEE 754浮点,而double数据类型是双精度64位IEEE 754浮点。

这是什么意思?我什么时候应该使用float而不是double?


8
当内存使用至关重要时,应使用浮点数而不是双精度数。如果需要更精确的计算,请使用双精度。
Everv0id 2014年

12
@ Everv0id:我不确定任何情况下内存都太紧,以至于不得不牺牲空间的准确性。(为方便起见,您正在使用Java ...)在某些情况下需要调用它,但是在我的实践中,我很少看到它。如果您想详细说明为什么您认为这是个好主意,那么以一个实例为例提供答案将是值得的。
Makoto 2014年


5
@Makoto实际上,我从没用过花车,只有双打。但是(理论上)可能存在应保留大量浮点数的应用程序,因此2倍的内存使用量可能至关重要。从理论上讲,ofc; 实际上,您总是可以购买另一台服务器
Everv0id 2014年

3
我使用4字节甚至2字节的固定精度数字来节省内存,但是除非您拥有数十亿个固定精度数字,否则不值得。您用“ double”而不是“ float”(它还有一个字母)花费的时间比您使用的额外内存多1000倍,但是如果使用double而不是使float您避免了与精度相关的错误,那是值得的。
彼得·劳里

Answers:


259

维基百科页面上这是一个良好的开端。

总结一下:

  • float以32位表示,带有1个符号位,8个指数位和23位有效数(或从科学记号中得出的结果:2.33728 * 10 12; 33728为有效数)。

  • double 用64位表示,带有1个符号位,11个指数位和52个有效位。

默认情况下,Java double用来表示其浮点数字(因此3.14键入文字double)。这也是数据类型,它将为您提供更大的数字范围,因此,我强烈建议在上使用它float

有可能是某些库,实际上迫使你的使用float,但一般-除非你能保证你的结果将是小到足以适应float规定范围,那么最好与选择double

如果您需要准确性-例如,您不能使用不正确的十进制值(例如1/10 + 2/10),或者您正在使用货币进行任何操作(例如,在系统中表示$ 10.33),则使用BigDecimal,可以支持任意精度和类似情况的优雅处理。


4
在给定的示例中不是233728 ==尾数吗?我的意思是,整数部分还存储在哪里?
JaLoveAst1k 2016年

1
@ mathguy54:用科学计数法,2是整数整数,.33728是尾数。 这是对此的参考。
Makoto

5
我正在搜索浮点数和双打的信息,发现了这一点并需要发表评论:如果您使用不涉及小数美分的货币进行任何操作,则使用BigDecimal是荒谬的。通用货币是离散数据,因此您应该使用整数数据类型。(这是年轻程序员经常犯的错误之一,因为我们使用。来将美分与美分分开,所以他们认为这是一个浮点值。不是。)
Trixie Wolf

2
@TrixieWolf,您能否更具体一点,是否建议使用两个整数(整数和十进制部分)?您正在谈论的是通用货币,其余的呢?一些金额用6位小数表示,因此您不能简单地计算*100。拜托,您在这里有个要点,但您可以更精确吗:)
AxelH '16

9
@AxelH除了可能存在小数美分的财务计算中间,金钱始终是离散的。您将使用一种整数类型来存储数据。因此,5.34美元将被存储为534。整数部分中的美元部分为val / 100,而整数部分中的美分为val%100,其中%表示余数。对于在小数点后还有更多位数的货币,由于它是离散的,因此仍应存储为整数。即使它不是离散的,通常您还是希望大多数时候都退回到离散存储,因为它很精确,因此您不会因舍入错误而损失金钱。
Trixie Wolf

72

浮法给你大约。6-7位小数位数的精度,而双精度则为您提供约。15-16岁。同样,数字范围更大,为两倍。

双精度型需要8个字节的存储空间,而浮点型则仅需要4个字节。


13

浮点数,也称为实数,用于评估需要小数精度的表达式。例如,诸如平方根之类的计算,或诸如正弦和余弦之类的超越计算,会得出其精度需要浮点类型的值。Java实现了标准(IEEE–754)浮点类型和运算符集。有两种浮点类型,浮点型和双精度型,分别代表单精度和双精度数。它们的宽度和范围如下所示:


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


浮动

float类型指定使用32位存储的单精度值。单精度在某些处理器上更快,并且占用的空间是双精度的一半,但是当值很大或很小时,它将变得不精确。当您需要小数部分但不需要很高的精度时,float类型的变量很有用。

以下是一些示例float变量声明:

浮于高温,低温;


如double关键字所示,双精度使用64位存储值。实际上,在一些针对高速数学计算进行了优化的现代处理器上,双精度比单精度要快。所有先验数学函数(例如sin(),cos()和sqrt())都返回双精度值。当您需要在许多迭代计算中保持准确性,或者要处理大数值时,双精度是最佳选择。


我们应该何时使用float和double明确澄清了这个答案。为什么不呢?
Ye Win 2014年

8
在Java中,也不float是将double类型最好用于货币,因为它们为四舍五入带来了机会。本文将详细介绍:javapractices.com/topic/TopicAction.do?Id=13
PPartisan 2015年

1
“浮点数在代表美元和美分时会很有用。” -不,不,不,nononono。永远不要将货币存储为浮点数/倍数。
减少活动

2

尽管如此,Java似乎还是倾向于使用double进行计算:

以我今天早些时候编写的程序为例,当我使用float时这些方法不起作用,但是当我用double替换float(在NetBeans IDE中)时,现在可以很好地工作:

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

我今天有同样的问题。这种偏见的背后原因可能是什么?
沙池

2

这将产生错误:

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

/MyClass.java:3:错误:不兼容的类型:可能有损从double转换为float float a = 0.5;

这将很好地工作

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

这也将很好地工作

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

原因:Java默认情况下将实数存储为两倍,以确保更高的精度。

Double占用更多空间,但在计算过程中更精确,而float占用更少空间,但精度不高。


1

根据IEEE标准,float是实数的32位表示,而double是64位表示。

在Java程序中,我们通常通常会看到double数据类型的使用。只是为了避免溢出,因为使用double数据类型可以容纳的数字范围大于使用float时的范围。

另外,当需要高精度时,鼓励使用双精度。很久以前实现的几种库方法仍然需要使用float数据类型(这仅是因为它是使用float实现的,别无其他!)。

但是,如果确定您的程序需要较小的数目,并且使用float不会发生溢出,那么使用float会大大提高您的空间复杂度,因为float需要一半的内存,是两倍的内存。


0

本示例说明了如何从Java的float中提取符号(最左边的位),指数(后面的8位)和尾数(最右边的23位)。

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

相同的方法可以用于double运算(11位指数和52位尾数)。

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

信用:http : //sj.github.io/java-float/


0

对于精确的计算,应使用double而不是float;在使用不太精确的计算时,请使用float而不是double。浮点数仅包含十进制数,而双精度数包含IEEE754双精度浮点数,这使得更容易包含和计算数字。希望这可以帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.