[转]double与BigDecimal
转自:http://superivan.iteye.com/blog/963628
[1] 精确的浮点运算:
在Java里面,有时候为了保证数值的准确性需要精确的数据,先提供一个例子就可以发现问题了:
public class FloatNumberTester {
public static void main(String args[]){
System.out.println(0.05+0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.3 / 100);
}
}
按照我们的期待,上边应该是什么结果呢,但是看输出我们就会发现问题了:
这样的话这个问题就相对严重了,如果我们使用123.3元交易,计算机却因为1.2329999999999999而拒绝了交易,岂不是和实际情况大相径庭。
[2] 四舍五入:
另外的一个计算问题,就是四舍五入。但是Java的计算本身是不能够支持四舍五入的,比如:
public class GetThrowTester {
public static void main(String args[]){
System.out.println(4.015 * 100.0);
}
}
这个输出为:
401.49999999999994
所以就会发现这种情况并不能保证四舍五入,如果要四舍五入,只有一种方法java.text.DecimalFormat:
import java.text.DecimalFormat;
public class NumberFormatMain {
public static void main(String args[]){
System.out.println(new DecimalFormat("0.00").format(4.025));
System.out.println(new DecimalFormat("0.00").format(4.024));
}
}
上边代码输出为:
4.02
4.02
发现问题了么?因为DecimalFormat使用的舍入模式, 舍入模式 详情参见本文最后部分。
[3] 浮点输出:
Java浮点类型数值在大于9999999.0就自动转化成为科学计数法,看看下边的例子:
public class FloatCounter {
public static void main(String args[]){
System.out.println(9969999999.04);
System.out.println(199999999.04);
System.out.println(1000000011.01);
System.out.println(9999999.04);
}
}
9.96999999904E9
1.9999999904E8
1.00000001101E9
9999999.04
但是有时候我们不需要科学计数法,而是转换成为字符串,所以这样可能会有点麻烦。
总结:
所以在项目当中,对于浮点类型以及大整数的运算 还是尽量不要用double,long等基本数据类型以及其包装类,还是用Java中提供的BigDecimal,BigInteger等大数值类型来代替吧。
但这里特别说明一下BigDecimal类的两个构造函数的区别,他们分别是:
new BigDecimal(String val ) 和 new BigDecimal(double val )
先看例子:
public class BigDecimalMain {
public static void main(String args[]){
System.out.println(new BigDecimal(123456789.01).toString());
System.out.println(new BigDecimal("123456789.01").toString());
}
}
输出结果有一次令人意外了,同时两者之间的区别也一目了然了:
123456789.01000000536441802978515625
123456789.01
所以在 就是想利用double原始类型进行了相关计算之后再转成BigDecimal类型 的场合下,为了防止精度出现偏离,建议使用参数为String类型的该构造方法。即new BigDecimal(String val )。
补充:
- BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,由于创建对象会引起开销,因此它们不适合于大量的数学运算,应尽量使用long、float、double等基本类型做科学计算或者工程计算。设计BigInteger与BigDecimal的目的是用来精确地表示大整数和小数,常用于商业计算中。
- BigDecimal够造方法的参数类型有4种,其中的两个用BigInteger构造,另一个是用double构造,还有一个使用String构造。应该避免使用double构造BigDecimal,因为:有些数字用double根本无法精确表示,传给BigDecimal构造方法时就已经不精确了。比如,new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。使用new BigDecimal("0.1")得到的值是0.1。因此,如果需要精确计算,用String构造BigDecimal,避免用double构造,尽管它看起来更简单!
- equals()方法认为0.1和0.1是相等的,返回true,而认为0.10和0.1是不等的,结果返回false。方法compareTo()则认为0.1与0.1相等,0.10与0.1也相等。所以在从数值上比较两个BigDecimal值时,应该使用compareTo()而不是 equals()。
- 另外还有一些情形,任意精度的小数运算仍不能表示精确结果。例如,1除以9会产生无限循环的小数 .111111...。出于这个原因,在进行除法运算时,BigDecimal可以让您显式地控制舍入。
[转]double与BigDecimal的更多相关文章
- Double与BigDecimal 比较
1] 精确的浮点运算: 在Java里面,有时候为了保证数值的准确性需要精确的数据,先提供一个例子就可以发现问题了: public class FloatNumberTester { public st ...
- float、double、BigDecimal的一些精度问题
float f = 280.8f;System.out.println(f*100);结果是什么?结果是:28080.0f(我是这么想的)实际结果是:28079.998 既然float处理有问题换do ...
- 【1】Java中double转BigDecimal的注意事项
项目遇到该问题 先上结论:不要直接用double变量作为构造BigDecimal的参数. 线上有这么一段Java代码逻辑: 1,接口传来一个JSON串,里面有个数字:57.3. 2,解析JSON并把这 ...
- java中四舍五入——double转BigDecimal的精度损失问题
代码: double d = -123456789012345.3426;//5898895455898954895989; NumberFormat nf = new DecimalFormat(& ...
- Java中double转BigDecimal的注意事项
先上结论:不要直接用double变量作为构造BigDecimal的参数! 线上有这么一段Java代码逻辑: 1,接口传来一个JSON串,里面有个数字:57.3. 2,解析JSON并把这个数字保存在一个 ...
- Double与BigDecimal 精度问题
转自:http://superivan.iteye.com/blog/963628 [1] 精确的浮点运算: 在Java里面,有时候为了保证数值的准确性需要精确的数据,先提供一个例子就可以发现问题了: ...
- 小数数据精度问题Double与BigDecimal
做项目的过程中涉及到小数问题的时候,一般我都用Double类型,但是经常出现*.999999998这种数据,然后自己再手动四舍五入,简直傻的要死. 明明就是一个1.51-1.38的问题,很简单怎么会得 ...
- Char、float、Double、BigDecimal
Char初识 char: char类型是一个单一的 16 位 Unicode 字符 char 在java中是2个字节("字节"是byte,"位"是bit ,1 ...
- Java浮点数float,bigdecimal和double精确计算的精度误差问题总结
(转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...
随机推荐
- arcmap搜索脚本错误
C盘/windows/temp,将temp文件夹右键单击,选择属性>选择安全>编辑>AlL APPLICATION PACKAGES>确定>关闭,如是操作即可解决 在cu ...
- 【spring boot】spring boot 前台GET请求,传递时间类型的字符串,后台无法解析,报错:Failed to convert from type [java.lang.String] to type [java.util.Date]
spring boot 前台GET请求,传递时间类型的字符串,后台无法解析,报错:Failed to convert from type [java.lang.String] to type [jav ...
- System.loadLibrary()的使用方法汇总
当使用System.loadLibrary()调用 Dll,两种方法: 1.设定环境变量. 比如:所编辑的Dll在目录“D:/cppProjects/nativecode/release”内,将这个路 ...
- java nio 映射文件内容到内存
FileChannel 的一个最好的功能就是能将文件的某个部分直接映射到内存.这要感谢 FileChannel.map() 方法,这个方法有下面三个参数: mode:映射到内存需要指定下面三种模式之一 ...
- 关于CSS中的float可能出现的小问题
关于CSS中的float可能出现的小问题 前言:最近学习CSS的float所遇到点小问题,然后顺便分享给大家. 一.什么是CSS以及float (一) CSS概述 CSS是层叠样式表(英文全称:Cas ...
- 关于GreenPlum的一些整理
Greenplum数据库架构 Greenplum数据库基本由PostgreSQL核心增强数据库实例组合并衔接成的数据库管理系统,即Greenplum数据在PostgreSQL基础上扩展开发,每个Gre ...
- 在ubuntu中搜索文件或文件夹的方法
版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/dcrmg/article/details/78000961 1. whereis+文件名 用于程序名的搜索 ...
- Unicode 和 UTF-8 的区别
作者:于洋链接:https://www.zhihu.com/question/23374078/answer/69732605来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- [转]Redis作者:深度剖析Redis持久化
From : http://www.iteye.com/news/24675 Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等 ...
- 如何确定HyperThreading是否在Linux上已开启?
命令如下: dmidecode -t processor | grep HTT 参考资料 ============= https://unix.stackexchange.com/questions/ ...