`
yinwufeng
  • 浏览: 285272 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

float或double 精度确实原因

阅读更多
由于对float或double 的使用不当,可能会出现精度丢失的问题。问题大概情况可以通过如下代码理解
public class FloatDoubleTest {
  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下没办法表示。于是带着这个问题,做了一次关于float和double学习,做个简单分享,希望有助于大家对java 浮点数的理解。

关于 java float double

Java 语言支持两种基本的浮点类型: float double java 的浮点类型都依据 IEEE 754 标准。IEEE 754 定义了32 位和 64 位双精度两种浮点二进制小数标准。

IEEE 754 用科学记数法以底数为 2 的小数来表示浮点数。32 位浮点数用 1 位表示数字的符号,用 8 位来表示指数,用 23 位来表示尾数,即小数部分。作为有符号整数的指数可以有正负之分。小数部分用二进制(底数 2 )小数来表示。对于64 位双精度浮点数,用 1 位表示数字的符号,用 11 位表示指数,52 位表示尾数。如下两个图来表示:

float(32位):

float

double(64位):

double

都是分为三个部分:

(1) 一个单独的符号位s 直接编码符号s

(2)k 位的幂指数E移码表示

(3)n 位的小数,原码表示

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

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

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

输出结果如下:

Double:100000101110011000101100111100101110000000000000000000000000000

Float:1001011100110001011001111001100

对于输出结果分析如下。对于 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 类型来转换。

分享到:
评论

相关推荐

    C语言学习笔记(结合教程)

    浮点类型的精度在<float.h>头文件中有规定,例如,float通常有6位有效数字,double有15位,这影响了数值转换时的精度保持。 理解这些基础知识对于编写高效且可靠的C语言程序至关重要。在编程实践中,需要合理利用...

    Java中强制类型转换共2页.pdf.zip

    - **浮点型转换**:float可以自动转换为double,而double转换为float、float转换为int或long,或者任何整型转换为float或double都需要强制转换。浮点转换可能丢失精度,因为浮点数是近似表示的。 4. **类型转换...

    浮点型如何在内存中进行存储呢?(csdn)————程序.pdf

    浮点数家族包含三种主要类型:float、double和long double。它们在内存中占用的字节数分别为4字节、8字节和8字节(对于long double,其大小可能因平台而异,但通常为8字节)。 float类型的精度相对较低,可以表示...

    java基础及面试题(1.1)

    这里是对应java基础及面试题(1.0)的重要面试题 ...long到float不用强转,因为float表示的范围确实比long表示的范围大,虽然它只占4个字节,而long占8个字节,float是用科学记数法来表示数据的,long是用二进

    C数据类型与运算规则实用PPT课件.pptx

    - **实型变量**:通过关键字`float`或`double`来定义,其中`double`类型的精度更高,占用更多内存空间。例如: - `float f = 1.23;` - `double d = 1.23456789;` - **字符型类型及其表示**: - **字符常量**:...

    java类型转换大全

    1. **基本类型之间的转换**:Java中有八种基本数据类型,包括整型(byte, short, int, long)、浮点型(float, double)、字符型(char)以及布尔型(boolean)。它们之间可以进行隐式或显式转换。例如,较小的数值...

    01Swift 数据类型.docx

    - `Double` 至少可以存储 15 位数字的精度。 2. **`Float`**: - `Float` 用于存储 32 位浮点数。 - 当对精度要求不高时,可以选择使用 `Float`。 - `Float` 至少可以存储 6 位数字的精度。 #### 四、布尔类型...

    c#数值类型,转换和装箱拆箱

    值类型包括整型(如int, byte, short等)、浮点型(如float, double)、无符号类型(如uint, ulong)以及枚举类型(enum)和结构(struct)。这些类型存储的是实际的数据,当赋值或传递时,会复制整个数据的副本。 ...

    c语言程序设计习题及其答案

    A) int B) float C) double D) 不确定 **解析**: - 整型、浮点型和双精度型数据进行运算时,结果类型为参与运算的最大类型,即双精度型。 **答案**: C) double 15. **题目**: 在 C 语言中,char 型数据在...

    C语言类型转换-自动类型转换、强制类型转换、指针类型转换

    3. **避免隐式转换导致的错误**:当类型转换可能引起意料之外的行为时,如可能导致精度损失或溢出,可以使用强制转换明确指定预期行为。 ### 指针类型转换 (Pointer Type Conversion) 在C语言中,指针类型转换允许...

    2021-2022计算机二级等级考试试题及答案No.13305.docx

    - Java中的浮点型数据类型包括float和double,其中double具有更高的精度。 4. ASP.NET数据库访问: - 使用ASP.NET访问Sql Server数据库时,需要导入的命名空间是System.Data.SqlClient。 5. SQL索引创建: - ...

    2021-2022计算机二级等级考试试题及答案No.1059.docx

    `float` 是单精度浮点类型,而 `double` 是双精度类型,提供更高的精度。 #### 题目8: 计算机病毒特征 - **知识点**: - 传染性: 病毒能够自我复制并传播到其他系统。 - 潜伏性: 病毒可能隐藏在系统中一段时间而不...

    2021-2022计算机二级等级考试试题及答案No.14665.docx

    13. Java的浮点型数据分为float和double,double具有更高的精度。 14. 被删除的文件在回收站未清空前可以恢复,但一旦清空回收站,文件通常无法找回。 15. ASP.NET访问SqlServer数据库需要导入`System.Data....

    MySQL思维导图详解版

    浮点型如FLOAT和DOUBLE用于表示小数,但可能存在精度问题。DECIMAL或NUMERIC则能精确表示小数,适合处理货币等需要精确数值的场景。字符串类型包括VARCHAR、TEXT、MEDIUMTEXT和BLOB,用于存储文本和二进制数据。日期...

    【C# 基础精讲】C# 数据类型概述

    - 浮点型:`float`(单精度浮点数,32位),`double`(双精度浮点数,64位)。浮点数用于处理小数部分的数值,通常在科学计算中使用。 - 字符型:`char`,用于存储单个字符,如字母、数字或其他符号,它占16位。 - ...

    Java 编程军规.docx

    - **解释**:由于浮点数的精度限制,直接使用float或double进行金融级的计算可能会产生误差。 - **实践建议**:对于需要高精度的计算场景,推荐使用BigDecimal类进行处理。 ### 总结 遵循以上军规不仅有助于提高...

    2021-2022计算机二级等级考试试题及答案No.13288.docx

    23. Java中数值类型的转换,从小到大依次为byte→short→int→long→float→double。 24. 图表可以与数据放在不同的工作表中,Excel允许这种分离。 25. 由于题目缺失,无法提供程序段运行结果。 这些知识点涉及到...

    2021-2022计算机二级等级考试试题及答案No.14968.docx

    16. Java语言的浮点型数据分为float和double,double具有更高的精度。 17. 给定的C程序计算结果是B.2,1。程序中a=d/10%9的结果为2,b=a&&( -1)的结果为1。 18. 在程序开发中,导入其他包的类通常使用import关键字...

    JAVA常见数类型大小.docx

    - **float**:长度为4个字节(32位),使用IEEE 754单精度浮点格式,取值范围大约是-3.4 * 10^38到3.4 * 10^38,精确到约6-7位小数。 - **double**:长度为8个字节(64位),同样遵循IEEE 754双精度浮点格式,取值...

    2021-2022计算机二级等级考试试题及答案No.16748.docx

    7. Java浮点型:Java中的浮点型数据包括float和double,其中double具有更高的精度。 8. Windows快捷键:Ctrl+C是Windows中的复制快捷键,与菜单中的复制功能相同,所以正确答案是正确。 9. PowerPoint自定义动画:...

Global site tag (gtag.js) - Google Analytics