`
六十三
  • 浏览: 44234 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java float double为什么精度会丢失

阅读更多

由于对float或double 的使用不当,可能会出现精度丢失的问题。问题大概情况可以通过如下代码理解:

 

public class Num
{
	public static void main(String[] args)
	{
		float f = 20014999;
		double d = f;
		double d2 = 20014999;

		System.out.println("f=" + f);
		System.out.println("d=" + d);
		System.out.println("d2=" + d2);
	}
}
//结果

f=2.0015E7
d=2.0015E7
d2=2.0014999E7

  从输出结果可以看出double 可以正确的表示20014999 ,而float 没有办法表示20014999 ,得到的只是一个近似值。这样的结果很让人讶异。20014999 这么小的数字在float下没办法表示。

 

那么 20014999 为什么用 float 没有办法正确表示?

 

 

结合float和double的表示方法,通过分析 20014999 的二进制表示就可以知道答案了。

以下程序可以得出 20014999  double  float 下的二进制表示方式。

 

public class FloatDouble
{
	public static void main(String[] args)
	{
		double d = 8;
		long l = Double.doubleToLongBits(d);
		System.out.println(Long.toBinaryString(l));
		float f = 8;
		int i = Float.floatToIntBits(f);
		System.out.println(Integer.toBinaryString(i));
	}
}
 

 

输出结果如下:

 

Double:100000000100000000000000000000000000000000000000000000000000000

Float:1000001000000000000000000000000

对于输出结果分析如下。对于都不 double 的二进制左边补上符号位 0 刚好可以得到 64 位的二进制数。根据double的表 示法,分为符号数、幂指数和尾数三个部分如下:

0 10000010111 0011000101100111100101110000000000000000000000000000

对于 float 左边补上符 号位 0 刚好可以得到 32 位的二进制数。 根据float的表示法, 也分为 符号数、幂指数和尾数三个部分如下 

0 10010111 00110001011001111001100

绿色部分是符号位,红色部分是幂指数,蓝色部分是尾数。

对比可以得出:符号位都是 0 ,幂指数为移码表示,两者刚好也相等。唯一不同的是尾数。

 double 的尾数 为: 001100010110011110010111 0000000000000000000000000000 省略后面的零,至少需要24位才能正确表示 

而在 float 下面尾数 为: 00110001011001111001100 ,共 23 位。

为什么会这样?原因很明显,因为 float尾数 最多只能表示 23 位,所以 24 位的 001100010110011110010111  float 下面经过四舍五入变成了 23 位的 00110001011001111001100 。所以 20014999  float 下面变成了 20015000 
也就是说
 
20014999 虽然是在float的表示范围之内,但  IEEE 754  float 表示法精度长度没有办法表示出 20014999 ,而只能通过四舍五入得到一个近似值。

总结:

浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是 因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用 float  double 作精确运 算的时候要特别小心。
可以考虑采用一些替代方案来实现。如通过
 
String 结合 BigDecimal 或 者通过使用 long 类型来转换。

 

 

 

 

 

分享到:
评论

相关推荐

    解决java数值范围以及float与double精度丢失的问题

    解决java数值范围以及float与double精度丢失的问题 Java中的数值范围和浮点数精度问题是许多开发者经常遇到的问题。下面我们将详细探讨Java中的数值范围、float和double类型的精度问题,并且提供解决方案。 一、...

    Java 精确计算-double-float-String

    5. **转换类型**:如果需要将`BigDecimal`转换回`double`或`float`,可以使用`doubleValue()`和`floatValue()`方法,但要注意这可能会丢失精度。 在实际开发中,`BigDecimal`的使用可以确保计算结果的准确无误,但...

    详解java中float与double的区别

    这里有一个小知识:既然 float 和 double 型用来表示带有小数点的数,那为什么我们不称 它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。当一个数如 50.534,转换成科学计数法的...

    Java中double类型下出现精度计算错误情况下出力方法

    这个问题其实不是JAVA的bug,因为计算机本身是二进制的,而浮点数实际上只是个近似值,所以从二进制转化为十进制浮点数时,精度容易丢失,导致精度下降。  要保证精度就要使用BigDecimal类,而且不能直接从double...

    Java与MySQL中小数保存问题解析.pptx.pptx

    常见问题还包括在进行浮点数运算时可能出现的精度丢失,以及在设计数据库表结构时选择合适的数据类型。例如,如果业务逻辑要求精确存储和计算小数,那么选择DECIMAL而非FLOAT或DOUBLE会更为合适。 总的来说,理解和...

    float型和double型数据的存储方式1

    在Java中,当从float强制转换为double时,理论上数值不会改变,但由于初始的存储精度限制,可能存在微小的误差。这种误差在处理大量浮点运算或高精度要求的应用中是需要特别注意的,因为它可能会影响计算结果的准确...

    Java源码获取浮点数类型的最大最小值

    同时,在处理非常小的数值时,确保不小于`float`或`double`的最小值,可以防止因为数值过小而导致的精度丢失。 此外,浮点数的比较也需要注意,由于浮点数的不精确性,直接使用`==`进行比较可能会导致错误的结果。...

    java代码-1·byte short int 在计算是会自动转化为int 2.float double 为近似值,byte short int 转化时可能会精确丢失 3.把大类型转化小的类型时可能会丢失

    // 高位的位数会被截断,可能会导致精度丢失 ``` 最后,我们要理解“把大类型转化为小的类型时可能会丢失”。当一个大数值类型(如long或double)转换为一个小数值类型(如byte、short或int)时,如果原始值超过了...

    java中double转化为BigDecimal精度缺失的实例

    在Java编程语言中,数值类型如`double`和`float`虽然方便进行浮点数运算,但它们在处理精度上存在一定的局限性。这主要是由于它们是基于二进制浮点数表示法,而非十进制。在进行计算时,某些十进制小数无法精确地...

    double类型转换

    尽管`double`类型能够提供比`float`类型更高的精度,但在实际应用中,由于浮点数的二进制表示方式,有时仍然会出现精度丢失的问题。尤其在进行数学运算或比较时,这种精度问题可能会导致不准确的结果。 ### 保留两...

    JAVA-type.rar_java Type

    但是,从double到float转换时,可能因精度丢失而改变数值。 六、字符与字符串转换 1. char转String:可以使用String类的构造函数,如String str = new String(new char[]{'c', 'h', 'a', 'r'});。 2. String转char...

    JAVA语法.pdf

    JAVA为所有成员变量提供了默认初始化,例如`byte`、`short`、`int`、`long`的默认值为0,`float`和`double`的默认值分别为0.0f和0.0,`boolean`的默认值为false,`char`的默认值为`\u0000`,对象类型的引用默认初始...

    Java数据类型操作包含转换代码实例.rar

    - float可以自动转换为double,但double不能自动转换为float,因为double的精度更高。 - 强制类型转换可能导致精度损失,如`(float) doubleValue`。 3. 字符型和数值型之间的转换: - char可以转换为int,因为它...

    java 常用基础类型之强制转换

    - 当从低精度类型转换为高精度类型时,Java会自动进行这种转换,无需显式强制转换。例如,`int`可以无损地转换为`long`,`float`或`double`。 - 字符串到数字的转换也是自动的,例如`Integer.parseInt()`和`Double...

    Test_float_to_long.rar_float_float linux

    浮点数是用于表示小数或大范围数值的类型,通常有单精度(float)和双精度(double)两种。在Java中,`float`占用32位,可以精确表示约6到7位小数;而`long`占用64位,用于存储大的整数。在进行浮点数到长整型的转换时,...

    Java面试笔试题大汇总(最全+详细答案)

    例如将double类型的值赋给float类型时需要进行类型转换,否则会引发编译错误,因为从double到float可能会丢失精度。同样,对于整数类型赋值给short时,若超出其范围也需要进行类型转换。 5. Java的goto关键字 Java...

    Java 自动提升的资源

    - 浮点类型(float, double):float会被提升为double,因为double具有更高的精度。 - boolean类型不参与数值运算,但可以进行逻辑运算。在布尔表达式中,true和false被视为1和0,但这不是数据类型的提升,而是...

    Java中几种常用数据类型之间转换的方法

    在 Java 中,int 类型的变量可以被强制转换为 short 类型的变量,但是需要注意的是,如果 int 类型的值超出了 short 类型的范围,将会导致精度丢失。例如: short shortvar = 0; int intvar = 0; intvar = shortvar...

Global site tag (gtag.js) - Google Analytics