在初学Java的时候,一般我们都会从基本的数据类型开始学习,而在基本数据类型中,我认为double类型是比较难理解的,并且在以后的学习或工作中,在double类型数据这遇到的坑也是极多的。例如下面的这样一个程序public static void main(String[] args) {

System.out.println(2.0-1.1);

}

很多人会认为上面的程序会打印出0.9,但实际上,它打印的却是0.8999999999999999,这是为什么呢?

首先介绍一下,十进制小数是怎么转换为二进制数的,举个例子3.75

首先取出3.75的小数部分0.75,将其乘以要转换的进制的进制数,在这里也就是2,乘以2后得到结果1.5,取1.5的整数部分作为二进制小数的小数部分的第一位,再取1.5的小数部分0.5,乘以2后得到1.0,将1.0的整数部分1作为小数部分的第二位。以此类推,直到最后得到值0或形成无限循环。3.75转换为二进制数就是11.11;

但是我们知道在Java中double类型的数据占8个字节,所以对于无限循环的二进制小数我们只能取到它的近似值,就比如说1.1。

下面自己写了一个将double类型的数转换为二进制的程序public static void main(String[] args) {

doubleToBinary(3.75000000);

doubleToBinary(173.8125);

doubleToBinary(1.10);

}/**

* 10任何次负幂都不能精确地被表示为一个长度有限的二进制数

* @param d

*/public static void doubleToBinary(double d) {    // 获得double类型的整数部分

int intPart = (int) d;

String tempStr = d + "";    // 获得double类型数的字符串形式的小数部分

String decimalPartStr = tempStr.substring(tempStr.indexOf("."));

BigDecimal decimal = new BigDecimal(decimalPartStr);    // 获得小数点后面的位数

int precision = decimal.precision();    // 最终的小数部分二进制字符串

String decimalPartBinary = decimalPartToBinary(Double.parseDouble(decimalPartStr), precision);

System.out.println(Integer.toBinaryString(intPart) + "." + decimalPartBinary);

}/**

* 将小数部分转换为二进制字符串

* @param decimalPart 小数部分

* @param precision   原始数的小数部分位数

* @return*/public static String decimalPartToBinary(double decimalPart, int precision) {    // 转换为整型

long decimalPartLong = (long) (Math.pow(10, precision) * decimalPart);

String temp = "";    int i = 0;    while (precision > 0 && i

decimalPartLong = decimalPartLong * 2;

temp += (int) (decimalPartLong / Math.pow(10, precision));        //取得除第一位之后的数,并转换为字符串

String str = (long) (decimalPartLong % Math.pow(10, precision)) + "";        if (str.charAt(str.length() - 1) == '0' && str.length() != 1) {            //去掉数最后面的0

decimalPartLong = Long.parseLong(str.substring(0, str.length() - 1));

} else {

decimalPartLong = Long.parseLong(str);

}        if (decimalPartLong == 0) {            break;

}

++i;

precision = (decimalPartLong + "").length();

}    return temp;

}

上面程序中的main方法输出的值为11.1110101101.11011.0001100110011001100110011001100110011001100110011001100110011001

通过上面的程序,我们很容易看到测试数据1.10在小数部分是无限循环的,1.10并不能精确地表示为一个double,因此它在Java中被表示为最接近它的double值。既然Java中是对double不能精确表示的数以近似值去存储的,那么在一些需要精确计算的地方就有可能出现错误,甚至产生意想不到的结果。比如说在业务中经常碰到的货币计算。那么如何解决这个问题呢?

1.使用执行精确小数运算的BigDecimalAPI,但这里要说明一点,最好(一定)要用BigDecimal(String val)构造方法,而不要使用BigDecimal(double val),因为BigDecimal(double val)构造方法将会使用它的参数val的精确值返回一个BigDecimal,比如new BigDecimal(1.1)将会返回一个表示1.100000000000000088817841970012523233890533447265625的BigDecimal。

2.使用整数类型进行计算,比如说int或long。将2.0元转换为200分去计算,这样System.out.println((200-110)+ "分")将会打印出正确的结果90分。

总而言之呢,在需要精确计算的地方要避免使用float和double的数据。如果上面的程序有错的地方,请指出,共同学习,谢谢。

作者:Jadyn

链接:https://www.jianshu.com/p/82688c94c58c

java double 类型_关于Java中的double类型数据相关推荐

  1. java鸭子类型_语言设计中的鸭子类型风格

    在动态语言的世界里一直流传着一种叫做鸭子类型的风格,其来自谚语:"如果行鸭子一样走路,像鸭子一样呱呱叫,那它就是一只鸭子". 从鸭子类型,我们可以联想到它的推导,并不在乎类型的真正 ...

  2. 凡是函数中未指定存储类型_凡是函数中未指定存储类型的局部变量,其隐含的存储类别为    。...

    凡是函数中未指定存储类型的局部变量,其隐含的存储类别为 . 答:自动(auto) 婴儿1.5岁-2岁时,使用的句子主要是( ). 答:电报句 监控批量成本预测需要() 答:选择预测所需的成本研究 现行 ...

  3. java converter转换器_在SpringMVC中设置自定义类型转换器Converter

    前言 在SpringMVC中为我们提供了许多内置的类型转换器,当我们在HTML表单中发起一个请求时,Spring会根据表单项中name属性的值映射到POJO的属性名,调用相对性属性的set方法帮我们把 ...

  4. c++ enum 给定类型_讲解C++中的枚举类型以及声明新类型的方法

    C++枚举类型如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型.所谓"枚举"是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内.声明枚举类型用 ...

  5. java中double身高_用JAVA编一个程序 输入10名同学的身高,找出最高升高,要求使用对象数组类型的带参方法来实现...

    用JAVA编一个程序 输入10名同学的身高,找出最高升高,要求使用对象数组类型的带参方法来实现 关注:285  答案:5  mip版 解决时间 2021-02-05 07:44 提问者女人不需要倾国倾 ...

  6. java double相加_解决java中两个double类型的值相加

    代码: /** * 提供精确的加法运算 * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(doub ...

  7. java中数值023是什么类型_【Java 教程(原创)】023.参数传值——引用类型参数的传值...

    马上注册,结交更多好友,享用更多功能^_^ 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 本帖最后由 零度非安全 于 2017-3-12 14:03 编辑 点击图片穿越到 索引帖,听说有惊喜 ...

  8. resultset java 类型_关于JAVA中Resultset的类型

    JAVA中Resultset是一个类 而不是一个方法.记住啊. 结果集(ResultSet)是数据中查询结果返回的一种对象,可以说结果集是一个存储查询结果的对象,但是结果集并不仅仅具有存储的功能,他同 ...

  9. java char 计算_经典Java面试题之Java中Char类型的运算

    经典Java面试题之Java中Char类型的运算 char在java中称为"字符型",占2个字节.本文是百分网小编搜索整理的关于经典Java面试题之Java中Char类型的运算,有 ...

最新文章

  1. mysql sql w3cschool_SQL复习(w3school)笔记
  2. 【错误记录】Visual Studio 中编译 NDK 报错 ( error : cannot use ‘throw‘ with exceptions disabled )
  3. 深入Java集合学习系列:LinkedHashSet的实现原理
  4. 无法序列化会话状态。请注意,当会话状态模式为“StateServer”或“SQLServer”时,不允许使用无法序列化的对象或 MarshalByRef 对象。...
  5. (专题四)01 二维曲线
  6. SpringBoot 跨域请求
  7. 李飞飞为什么会离职 Google?
  8. oracle中的rownum
  9. execute、executeUpdate、executeQuery三者的区别
  10. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_6_字节输出流写多个字节的方法...
  11. 按键精灵怎么用 android,按键精灵安卓版怎么用
  12. 下载各种在线视频及字幕
  13. 易语言5.4一键破解工具
  14. 关于matlab影像处理imhist直方图均衡化问题
  15. 【办公自动化】基于Arcpy建立GIS三调转换工具箱,23万图斑shp文件分分钟转换完成
  16. 《董明珠的真面目,她到底有多狠》调查问卷
  17. 京东充值系统现漏洞 被恶意盗刷
  18. 小仙女手账的神仙句子
  19. 轻松打造xfce4轻快桌面
  20. NLPIR-ICTCLA2018分词用户大会线上抢票报名开始

热门文章

  1. Sublime Text:选择变量的所有实例并编辑变量名称
  2. 数据分析前景怎么样?好不好?
  3. 苹果电脑(mac os x)键盘使用技巧
  4. zblog php wordpress,zblog和wordpress哪个好
  5. Havel算法-Python实现
  6. p标签换行导致的问题
  7. excel基础-固定某一列的输入内容
  8. C语言编程练习 念数字
  9. 使用Nuxt.js框架开发(SSR)服务端渲染项目
  10. Word文件如何查看字数