Java BigDecimal和double

 

BigDecimal是Java中用来表示任意精确浮点数运算的类,在BigDecimal中,使用unscaledValue × 10-scale来表示一个浮点数。其中,unscaledValue是一个BigInteger,scale是一个int。从这个表示方法来看,BigDecimal只能标识有限小数,不过可以表示的数据范围远远大于double,在实际应用中基本足够了。

下面提一下两个精度问题:
 
问题一:BigDecimal的精度问题(StackOverflow上有个家伙问了相关的问题
System.out.println(new BigDecimal(0.1).toString()); // 0.1000000000000000055511151231257827021181583404541015625
System.out.println(new BigDecimal("0.1").toString()); // 0.1
System.out.println(new BigDecimal(
Double.toString(0.1000000000000000055511151231257827021181583404541015625)).toString());// 0.1
System.out.println(new BigDecimal(Double.toString(0.1)).toString()); // 0.1

分析一下上面代码的问题(注释的内容表示此语句的输出)

第一行:事实上,由于二进制无法精确地表示十进制小数0.1,但是编译器读到字符串"0.1"之后,必须把它转成8个字节的double值,因此,编译器只能用一个最接近的值来代替0.1了,即0.1000000000000000055511151231257827021181583404541015625。因此,在运行时,传给BigDecimal构造函数的真正的数值是0.1000000000000000055511151231257827021181583404541015625。
第二行:BigDecimal能够正确地把字符串转化成真正精确的浮点数。
第三行:问题在于Double.toString会使用一定的精度来四舍五入double,然后再输出。会。Double.toString(0.1000000000000000055511151231257827021181583404541015625)输出的事实上是"0.1",因此生成的BigDecimal表示的数也是0.1。
第四行:基于前面的分析,事实上这一行代码等价于第三行
 
结论:
1.如果你希望BigDecimal能够精确地表示你希望的数值,那么一定要使用字符串来表示小数,并传递给BigDecimal的构造函数。
2.如果你使用Double.toString来把double转化字符串,然后调用BigDecimal(String),这个也是不靠谱的,它不一定按你的想法工作。
3.如果你不是很在乎是否完全精确地表示,并且使用了BigDecimal(double),那么要注意double本身的特例,double的规范本身定义了几个特殊的double值(Infinite,-Infinite,NaN),不要把这些值传给BigDecimal,否则会抛出异常。
 
问题二:把double强制转化成int,难道不是扔掉小数部分吗?
int x=(int)1023.99999999999999; // x=1024为什么?

原因还是在于二进制无法精确地表示某些十进制小数,因此1023.99999999999999在编译之后的double值变成了1024。

所以,把double强制转化成int确实是扔掉小数部分,但是你写在代码中的值,并不一定是编译器生成的真正的double值。
验证代码:
double d = 1023.99999999999999;
int x = (int) d;
System.out.println(new BigDecimal(d).toString()); // 1024
System.out.println(Long.toHexString(Double.doubleToRawLongBits(d))); // 4090000000000000
System.out.println(x); // 1024

前面提过BigDecimal可以精确地把double表示出来还记得吧。

我们也可以直接打印出d的二进制形式,根据IEEE 754的规定,我们可以算出0x4090000000000000=(1024)。

java bigDecimal and double的更多相关文章

  1. Java BigDecimal和double

    BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数 ...

  2. Java BigDecimal和double BigDecimal类

    BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数 ...

  3. Java浮点数float,bigdecimal和double精确计算的精度误差问题总结

    (转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...

  4. java 金额计算,商业计算 double不精确问题 BigDecimal,Double保留两位小数方法

    解决办法================== http://blog.javaxxz.com/?p=763 一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法 进行精 ...

  5. java中如何使用BigDecimal使得Double类型保留两位有效数字

    一.场景:从数据表中读出Decimal类型的数据直接塞给Double类型的对象时,并不会有什么异常. 如果要再此基础上计算,就会发生异常. 比如:读出数据为0.0092,将其乘以100,则变成了0.9 ...

  6. Java BigDecimal 转换,除法陷阱(转)

    源地址:   http://blog.csdn.net/niannian_315/article/details/24354251 今天在用BigDecimal“出现费解”现象,以前虽然知道要避免用, ...

  7. Java中的Double类型计算

    一.问题的提出: 如果我们编译运行下面这个程序会看到什么?public class Test{    public static void main(String args[]){        Sy ...

  8. MySQL中Decimal类型和Float Double的区别 & BigDecimal与Double使用场景

    MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形 ...

  9. java总结:double取两位小数的多种方法

    1.方法一 四舍五入: import java.math.BigDecimal; double f = 111231.5585; BigDecimal b = new BigDecimal(f); d ...

随机推荐

  1. 【Android】3.23 示例23--瓦片图功能

    分类:C#.Android.VS2015.百度地图应用: 创建日期:2016-02-04 一.简介 地图SDK自v3.6.0起,新增瓦片图层(tileOverlay), 该图层支持开发者添加自有瓦片数 ...

  2. cocos2d-x Schedule详解

    原理介绍 Cocos2d-x调度器为游戏提供定时事件和定时调用服务.所有Node对象都知道如何调度和取消调度事件,使用调度器有几个好处: 每当Node不再可见或已从场景中移除时,调度器会停止. Coc ...

  3. cocos2d-xV3.0rc 环境搭建

    一.下载 由于www.cocos2d-x.org很难打开,不知道是不是电信的问题,所以只好在cocoschina论坛里王哲大牛的帖子里找到了一个下载链接:http://126.am/GyU7l0 帖子 ...

  4. 每日英语:Robots To Revolutionize China

    A new worker's revolution is rising in China and it doesn't involve humans. With soaring wages and a ...

  5. LeetCode: Reverse Words in a String 解题报告

    Reverse Words in a String Given an input string, reverse the string word by word. For example,Given ...

  6. LeetCode: solveSudoku 解题报告

    Sudoku SolverWrite a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are in ...

  7. python学习笔记(22)--漫画生成html最终版

    说明(2017.3.14): 1. 在主文件夹生成一个main.html作为目录 2. 在每个子文件夹生成一个index.html作为看图网页 3. 通过python批量生成html网页,js配合进行 ...

  8. 【Unity】使用SceneManager加载/切换场景

    一.直接切换 老版的(已弃用!): Application.LoadLevel(int index); // 参数是场景编号 Application.LoadLevel(string name); / ...

  9. Java类型的生命周期

    以上就是我今天没有总结学习类加载器时候对类加载器仅有的知识,虽然有个大概印象,但是还是有点模糊.今天一口气总结一下,参考文献我就不列举了.本文不生产知识,只是知识的搬运工. 静态.class文件到内存 ...

  10. Activiti 获取定义

    ProcessDefinitionEntity d = (ProcessDefinitionEntity)((RepositoryServiceImpl)repositoryService).getD ...