浮点数据类型是单精度32位IEEE 754浮点数,双精度数据类型是双精度64位IEEE 754浮点数。
这意味着什么?我应该在什么情况下使用float而不是double,反之亦然?
浮点数据类型是单精度32位IEEE 754浮点数,双精度数据类型是双精度64位IEEE 754浮点数。
这意味着什么?我应该在什么情况下使用float而不是double,反之亦然?
了解更多关于浮点数的内容,可以参考维基百科页面。
总结如下:
float
占用 32 位,其中包括 1 个符号位、8 个指数位和 23 个尾数位(或从科学记数法得出的数字:2.33728*1012;33728 即为尾数)。
double
占用 64 位,其中包括 1 个符号位、11 个指数位和 52 个尾数位。
默认情况下,Java 使用 double
来表示其浮点数(因此,文字量为 3.14
的文字被视为 double
类型)。它也是可以提供更大数字范围的数据类型,所以强烈建议使用 double
而不是 float
。
可能有一些库实际上会强制您使用 float
,但通常情况下,除非您能保证结果小到可以适应 float
的预定范围,否则最好选择 double
。
如果需要精确度,例如不能有不准确的小数位(例如 1/10 + 2/10
),或者在处理货币时(例如将 $10.33 表示为系统中的数字),则使用 BigDecimal
即可,它可以支持任意数量的精度,并且可以优雅地处理这种情况。
一个float可以提供大约6-7位小数精度,而double可以提供大约15-16位。此外,double的数字范围更大。
一个double需要8个字节的存储空间,而一个float只需要4个字节。
浮点数也叫实数,用于计算需要小数精度的表达式。比如求平方根、三角函数(正弦和余弦)等运算得到的结果需要使用浮点类型来保证精度。Java 实现了标准(IEEE-754)的浮点类型和运算符。它们分为两种:float 和 double,分别表示单精度和双精度数。它们的位数和范围如下:
Name Width in Bits Range
double 64 1 .7e–308 to 1.7e+308
float 32 3 .4e–038 to 3.4e+038
浮点型(float)
浮点型指定了一种单精度值,使用 32 位存储空间。在某些处理器上,单精度比双精度更快,并且只需要一半的存储空间,但是当值非常大或非常小时,单精度值会变得不准确。当您需要小数部分但不需要高度精确度时,浮点型变量非常有用。
以下是一些浮点型变量声明的示例:
float hightemp, lowtemp;
双精度型(double)
双精度型,由 double 关键字表示,使用 64 位存储一个值。在现代某些优化为高速数学计算的处理器上,双精度实际上比单精度更快。所有的三角函数,如sin()、cos()和sqrt()等返回双精度值。当您需要在多个迭代计算中保持精度,或者操作大值数字时,双精度型是最佳选择。
float
也不推荐使用double
类型来处理货币,因为它们容易出现舍入误差。这篇文章详细介绍了其中的原因:http://www.javapractices.com/topic/TopicAction.do?Id=13。 - PPartisan这将会产生错误:
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以确保更高的精度。
Double在计算过程中占用更多的空间,但更加精确;而float占用更少的空间,但精度较低。
尽管如此,Java似乎偏向于使用double进行计算:
举个例子,我今天早些时候写的程序,在使用float时方法无法工作,但是当我将float替换为double(在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;
}
}
这个例子演示了如何从Java中的浮点数中提取符号(最左边的位)、指数(接下来的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));
float和double数据类型都是专门设计用于科学计算的,其中近似误差是可以接受的。如果精度是最重要的问题,则建议使用BigDecimal类代替float或double数据类型。来源:Java中的Float和Double数据类型
在进行精确计算时,应该使用double而不是float,而在进行不太精确的计算时则应该使用float而不是double。Float仅包含十进制数,但double包含IEEE754双精度浮点数,使得它更容易包含和计算数字。希望这可以帮到你。
double
而不是float
可避免精度相关的错误,那就值得这样做。 - Peter Lawrey