`
yuanc00
  • 浏览: 29388 次
社区版块
存档分类
最新评论

Java浮点数使用小结

    博客分类:
  • java
阅读更多

1.    引子

    平常在代码中,从不缺少使用浮点数的地方。浮点数可以使用float和double类型进行定义。默认都是使用的double类型,如果需要声明为float类型,需要显示地加F或者f,比如Float fNumber = 1.234F。往常个人在使用的时候,使用float居多(在java的基本类型中,Float是32位,4个字节;Double是64位,8个字节;所以float相对来说节省内存),近来踩了两个坑,觉得还是double比较省心。记录如下。

 

2.    问题1 – 精度错误

2.1 表现形式问题一示例如下。

    需要将一组对象转换成json,使用的json包是json-lib 2.2版本。


图2.1 json-lib包引用

 

图2.2 问题1示例
 
图2.3 问题1结果


    可以看到在将浮点数转换成json数据的时候,Float类型的浮点数会出现精度错误的问题。

 

2.2 问题原因

    排查原因,发现在json-lib的库里面,对于Float类型的数据,是先将其转换成Double类型之后,然后再进行处理的。处理代码如下。

 

图2.4 json-lib对于Float的处理


    Float的doubleValue方法是直接进行类型转换,即return (double)value。
    Float和Double在内存中的存储长度不同,将Float转换成Double类型的时候,如果直接取Float的doubleVlaue方法,会进行位数的补全;特别是在有小数部分的时候,这样是不能保证精度的,这样就引起了我们现在的问题。

 
2.3 解决方法

 

    解决问题的方法有两个思路。

  • 在整个系统中以double类型存储,替换掉现有的以float类型存储的方式;
  • 找到float类型转换成double类型的安全的方法。

    第一个思路,可以彻底的解决这个问题,但是对于一个系统来说,进行全局替换需要慎重,所以暂时不进行这样的修复;
    第二个思路,可以有以下几种方案。

  • 因为我们的精度要求保留到小数点之后的两位即可,所以可以将原值value乘以100,然后取long值,将结果再除以100.0转换成double类型;
  • 使用BigDecimal;
  • 先将float类型的数值转换成String,然后将String转换成Double类型的即可。比较了一下,调用Double.valueOf(String value)方法和直接新建Double对象(new Double(String value))都是可以的;但是前者只需要创建对象一次,后者需要新建两个Double对象,为了节省开销,使用了第一个方法进行了处理。

    解决问题的代码如下。
 

图2.5 问题解决


    先判断要处理的值是float类型,然后调用Double的valueOf方法进行处理。


3.    问题2 – 大数表示问题

3.1 表现形式


    解决了上面这个json输出的问题之后,又发现了一个问题。对于一些较大的数值,比如9999999.99;最终的输出结果为1.0E7,而不是预期的数值。


3.2 原因分析


    按理来说,float存储的范围应该远大于这个数值,经过一系列的调试,发现是float类型转换成String的时候出现的问题。进一步深入,发现是float类型的存储结构导致的。
    在java中,float类型存储的长度是32bit,double类型的存储长度是64bit。如下表所示。


表3.1 float和double在java中的存储

  符号位(bit) 指数位(bit) 尾数位(bit)
Float(32bit) 1 8 23
Double(64bit) 1 11 52


    其中:

  • 符号位表示数值的正负;
  • 指数位表示数值的取值范围,以补码形式存储;
  • 尾数位表示数值的精度。

    对于float来说,2^23=8388608;所以float类型的数值,如果有效数字的数值超过了8388608这个值,系统会自动找一个近似的结果进行代替。这也是我们这里存储9999999.99的时候,结果异常的原因。这个值在存储的时候就已经被处理成了1.0E7,所以不论采用什么方式进行处理,都不会有改善的。这里也说明,float类型,可以保证6-7位的有效数字(6位及以下是绝对可以保证的,但是7位的时候,这个有效数字的数值如果超过了8388608,就无法进行表示了)。
    对于double类型,2^52=4503599627370496;所以double类型的有效数字在15-16位。
    所以我们遇到的问题2,目前是没有办法进行解决的。后续还是安排使用double类型替换float类型。

 

4.    小结

     本文从两个问题说明了float类型的“坑爹”之处,如果不是对业务以及业务的发展特别有把握,还是建议使用double类型。

  • 大小: 9.6 KB
  • 大小: 55.6 KB
  • 大小: 5.3 KB
  • 大小: 9.6 KB
  • 大小: 11.7 KB
  • 大小: 11.7 KB
分享到:
评论

相关推荐

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    3.4 小结:基本数据类型—— Java中一切数据和运算的基础 63 3.5 习题 65 第4章 Java中的程序执行流程 67 教学视频:1小时57分钟 4.1 顺序执行 67 4.2 使用if-else让程序懂得判断 68 4.2.1 if语句 68 4.2.2 ...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    3.4 小结:基本数据类型—— Java中一切数据和运算的基础 63 3.5 习题 65 第4章 Java中的程序执行流程 67 教学视频:1小时57分钟 4.1 顺序执行 67 4.2 使用if-else让程序懂得判断 68 4.2.1 if语句 68 4.2.2 ...

    突破程序员基本功的16课.part2

    1.3 小结 第2课 对象与内存控制 2.1 实例变量和类变量 2.1.1 实例变量和类变量的属性 2.1.2 实例变量的初始化时机 2.1.3 类变量的初始化时机 2.2 父类构造器 2.2.1 隐式调用和显式调用 2.2.2 访问子类对象...

    javaSE代码实例

    1.5 小结 11 第2章 基本数据类型——构建Java 大厦的基础 12 2.1 源代码注释 12 2.1.1 单行注释 12 2.1.2 区域注释 12 2.1.3 文档注释 13 2.2 基本数据类型 14 2.2.1 整型 15 2.2.2 浮点型 17 ...

    Python编程入门经典

    1.1.4 小结 4 1.2 准备工作 4 1.2.1 在非Windows系统上安装 Python 3.1 5 1.2.2 使用Python Shell 5 1.3 开始使用Python——字符串 6 1.3.1 字符串概述 6 1.3.2 为什么需要引号 6 1.3.3 为什么有3种类型的引号 7 ...

    JAVA程序设计教程

    内容小结.........................................................................................................................12 思考与练习............................................................

    C++大学教程,一本适合初学者的入门教材(part2)

    小结 术语 自测练习 自测练习答案 练习 第2章 控制结构 2.1 简介 2.2 算法 2.3 伪代码 2.4 控制结构 2.5 if选择结构 2.6 if/e1se选择结构 2.7 while重复结构 2.8 构造算法:实例研究1(计数器控制重复) 2.9 ...

    C++大学教程,一本适合初学者的入门教材(part1)

    小结 术语 自测练习 自测练习答案 练习 第2章 控制结构 2.1 简介 2.2 算法 2.3 伪代码 2.4 控制结构 2.5 if选择结构 2.6 if/e1se选择结构 2.7 while重复结构 2.8 构造算法:实例研究1(计数器控制重复) 2.9 ...

    C语言入门经典(第4版)--源代码及课后练习答案

    1.10 小结 18 1.11 习题 18 第2章 编程初步 19 2.1 计算机的内存 19 2.2 什么是变量 21 2.3 存储数值的变量 21 2.3.1 整数变量 21 2.3.2 变量的命名 25 2.3.3 变量的使用 26 2.3.4 变量的初始化 28 2.3.5 ...

    java课程设计-科学计算器.doc

    认真按时完成课程设计报告,课程设计报告容包括:设计任务与要求、需求分析、 设计思路、详细设计、运行调试与分析讨论和设计体会与小结六个部分。 2 需求分析 2.1 设计背景 设计这个计算器主要是参考Windows操作...

    C++大学教程

    小结------------------------------------------------------------------27 术语------------------------------------------------------------------29 自测练习-----------------------------------------...

Global site tag (gtag.js) - Google Analytics