- 浏览: 1198086 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (361)
- java综合 (33)
- 项目管理 (10)
- 工作流 (6)
- spring (11)
- hibenate (17)
- struts (0)
- javascript,html,css,ajax,jquery (11)
- IDE (9)
- 生活 (0)
- 工作 (0)
- 杂记 (1)
- 数据库 (96)
- 服务器 (5)
- 可视编辑 (0)
- freemarker (6)
- 操作系统 windows (13)
- web页面 (6)
- jms (15)
- 调优 (4)
- 测试和bug管理 (2)
- 原理 (1)
- 項目-atf (17)
- 安全 (3)
- xml (4)
- 操作系统 liunx (21)
- 网络 (22)
- office (11)
- 设计 (2)
- 软件 (1)
- 数据库 mysql (6)
- 胖客户端-flex (1)
- 正则 (9)
- oracle- liunx (3)
- sql2000 (2)
- 模式 (1)
- 虚拟机 (2)
- jstl (2)
- 版本控制 打包工具 (0)
- AOP (1)
- demo (1)
- 小软件 (2)
- 感恩 (1)
- iphone 4 (1)
- 反欺诈业务经验整理 (0)
最新评论
-
sea0108:
mark
java内存模型 -
XingShiYiShi:
方便把:testPNR();具体实现发出来吗?谢谢
用正则表达式解析 航信的电子客票和pnr报文 -
wh359126613:
如果js和webservice不在同一个服务器上,有跨域问题如 ...
使用javascript调用webservice示例 -
雨飛雁舞:
...
oracle 动态性能(V$)视图 -
ouyang1224:
好东西
oracle 动态性能(V$)视图
(注:前面写了一个超大整数相加的类,参见: 超大整数相加,超过了long的范围,你要怎么做!,后来有朋友评论说BigDecimal可以完全实现我的这这个功能,刚开始的时候,我还不服气,据我所知那里有这样的类哦,后来报着说服他的心理去找了一下,呵呵,结果居然自己被说服了,确实有这么一回事,利用BigDecimal操作超大整数一样,也是先把要操作的数据转换为字符串型。使用BigDecimal可以进行高精度的工程运算,就不会计算中的精度发愁了,感谢原作者。)
转自:http://chongtianpig.netbei.com/51976.shtml
Java 浮点数精确计算 BigDecimal的用法
java.math.BigDecimal的用法?
Java 浮点数 精确计算
如果我们编译运行下面这个程序会看到什么?
public class Test{
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);
}
};
你没有看错!结果确实是
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
Java中的简单浮点数类型float和double不能够进行运算。不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。
这个问题相当严重,如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。
在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。现在让我们看看如何解决这个问题。
四舍五入
我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数,我们只能象这样(保留两位):
public double round(double value){
return Math.round(value*100)/100.0;
}
非常不幸,上面的代码并不能正常工作,给这个方法传入4.015它将返回4.01而不是4.02,如我们在上面看到的
4.015*100=401.49999999999994
因此如果我们要做到精确的四舍五入,不能利用简单类型做任何运算
java.text.DecimalFormat也不能解决这个问题:
System.out.println(new java.text.DecimalFormat("0.00").format(4.025));
输出是4.02
BigDecimal
在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal。BigDecimal一共有4个够造方法,我们不关心用BigInteger来够造的那两个,那么还有两个,它们是:
BigDecimal(double val)
Translates a double into a BigDecimal.
BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.
上面的API简要描述相当的明确,而且通常情况下,上面的那一个使用起来要方便一些。我们可能想都不想就用上了,会有什么问题呢?等到出了问题的时候,才发现上面哪个够造方法的详细说明中有这么一段:
Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances nonwithstanding.
The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal(".1") is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.
原来我们如果需要精确计算,非要用String来够造BigDecimal不可!在《Effective Java》一书中的例子是用String来够造BigDecimal的,但是书上却没有强调这一点,这也许是一个小小的失误吧。
解决方案
现在我们已经可以解决这个问题了,原则是使用BigDecimal并且一定要用String来够造。
但是想像一下吧,如果我们要做一个加法运算,需要先将两个浮点数转为String,然后够造成BigDecimal,在其中一个上调用add方法,传入另一个作为参数,然后把运算的结果(BigDecimal)再转换为浮点数。你能够忍受这么烦琐的过程吗?下面我们提供一个工具类Arith来简化操作。它提供以下静态方法,包括加减乘除和四舍五入:
public static double add(double v1,double v2)
public static double sub(double v1,double v2)
public static double mul(double v1,double v2)
public static double div(double v1,double v2)
public static double div(double v1,double v2,int scale)
public static double round(double v,int scale)
附录
源文件Arith.java:
import java.math.BigDecimal;
/**
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
* 确的浮点数运算,包括加减乘除和四舍五入。
*/
public class Arith{
//默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
//这个类不能实例化
private Arith(){
}
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
};
发表评论
-
介绍Java GC种类,并更换 调优GC
2011-03-04 03:42 2166转载自:http://blog.csdn.net/rola ... -
Daemonthread(守护线程)的含义
2011-03-03 20:39 1943http://fruitking.iteye.com/blog ... -
smc_5_1_0小例子
2010-06-25 15:33 0smc_5_1_0小例子 -
Hessian 例子
2010-06-25 15:27 0Hessian 例子 -
java小日历带农历(转)
2010-06-20 15:55 1513http://zengming526.iteye.com/bl ... -
Annotation exmaple
2009-12-14 09:44 1113如何使用注解的小例子 -
Java6 WebService @WebService
2009-12-11 10:39 43541. 新建一个JAVA project.2. 新建一个He ... -
JNI 数据类型转换
2009-11-18 12:01 21223Java代码 #include <jni ... -
JNI 返回结构体参数
2009-11-18 11:58 8891如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jn ... -
Map 四种同步方式的性能比较
2009-11-01 21:03 2000如果需要使 Map 线程安全,大致有这么四种方法: 1、使用 ... -
ConcurrentHashMap之实现细节
2009-11-01 21:00 2841ConcurrentHashMap是Java 5中支持高并发、 ... -
Java反射经典实例
2009-09-28 16:30 2025Java提供了一套机制来动态执行方法和构造方法,以及数组操作等 ... -
servlet 线程 安全 threadlocal (基础知识了)
2009-09-15 13:05 3251关键字: j2ee servlet 线程 ... -
java toString() ReflectionToStringBuilder
2009-06-18 11:31 2120@Override public String toStrin ... -
解决JAVA服务器性能问题
2009-04-13 01:51 2862解决JAVA服务器性能问题 ... -
java内存模型
2009-04-12 23:10 5659Weblogic系统管理总结(7.1/8.0)关于JVM内存管 ... -
Java线程总结
2009-04-12 20:32 1175在论坛上面常常看到初 ... -
删除字符串中的空格或将字符串的多个空格换位单个空格
2009-04-10 15:44 2504//将字符串的多个空格换位单个空格 public static ... -
Java 中文于unicode 互转
2009-04-06 03:08 3252关键字: java unicode convert 转换 ... -
Java EE 6体系结构的变革
2009-03-27 17:54 1503又看到 Reza 同学为 Java EE 6 奔走呼告了。如同 ...
相关推荐
在Java编程语言中,BigDecimal类是用于处理高精度、大范围浮点数的工具,它在需要精确计算的场景下非常关键。BigDecimal提供了避免浮点数运算中的精度损失的方法,适用于金融、会计等对精度有严格要求的领域。这篇...
总之,`BigInteger`和`BigDecimal`是Java中处理大整数和高精度浮点数的关键工具,它们的源代码为我们提供了深入学习和定制这两个类的机会。理解并掌握这些类的使用能极大地提升在处理数学计算时的精确性和效率。
Java中的BigDecimal是一种高精度的数据类型,它可以用来表示非常大的整数和小数,提供了丰富的数学运算功能。下面我们将对Java中BigDecimal的基本运算进行详细的介绍。 构造方法 BigDecimal有四种构造方法,但是...
UITextFiled控件,限制输入浮点数的整数以及小数的位数; .
**问题背景**:在Java中使用`double`或`float`类型进行计算时,可能会出现非预期的结果,这是由于浮点数的存储方式导致的精度损失问题。 **解决方案**: 1. **使用`BigDecimal`**:对于需要高精度计算的场景,推荐...
标题中的"Java 精确计算 - double-float-String"指向的是Java中处理浮点数(double和float)以及字符串表示的数值时可能遇到的精度问题,以及如何通过特定方法实现精确计算。描述中提到的链接指向了一个具体的博客...
为了解决这个问题,开发者们引入了`BigDecimal`类库的概念,它在Java中被广泛使用,用于进行高精度的算术运算。本文将详细介绍JavaScript版的`BigDecimal`类库,以及如何在JavaScript环境中实现精确计算。 ...
在Java编程语言中,`BigDecimal` 类位于 `java.math` 包下,它提供了一种进行高精度和任意精度的十进制算术运算的方法。`BigDecimal` 是为那些需要精确数值计算的场景设计的,比如金融计算或会计应用,因为普通的 `...
Java 使用 BigDecimal 进行高精度计算的示例代码 在 Java 中,浮点类型的数值计算存在舍入误差的问题,因为浮点数不是精确值。因此,在进行高精度计算时,需要使用 BigDecimal 类来避免舍入误差。 首先,为什么...
例如,对于单精度浮点数,我们需要考虑符号位,将指数从偏移值中减去,然后计算尾数乘以2的指数次方。 2. **十进制到二进制**:这个过程通常通过算法实现,如格雷戈里·查尔斯·怀特利(Gregory Chaitin)的快速...
在Java中使用正则表达式来判断字符串是否符合整数、小数或实数的格式是一种常见且有效的做法。在编程中,我们经常需要对输入的字符串进行格式验证,以确保它们符合预期的数值格式,尤其是在处理财务数据、用户输入...
在Java编程语言中,`BigDecimal`类是用于表示和操作大数(通常涉及财务或精确数学计算)的重要工具。由于浮点数(如`float`和`double`)在计算机中是以近似值存储的,这可能导致计算结果的不精确性,尤其是在进行...
BigDecimal是一种可以处理任意精度的十进制浮点数的数据类型,它通常用于金融或会计等需要高精度计算的领域,因为在这些场景中,浮点数的精度丢失可能导致错误的结果。 在计算机科学中,浮点数(如`float`和`double...
总的来说,Java中解决浮点数精度问题的关键是使用BigDecimal类,并且要注意构造方法的选择,避免在转换过程中引入额外的精度损失。在编写涉及金融计算或需要高度精确性的程序时,使用BigDecimal是最佳实践。同时,...
`BigDecimal` 用于处理精确的浮点数运算,适合财务或金融计算,因为它可以避免浮点数计算中的精度问题。而 `Integer` 是 Java 中的整数类型,它只能存储整数值。在某些情况下,我们可能需要将 `BigDecimal` 对象转换...
本文将详细介绍如何在Java中实现BigDecimal到Double的转换,并探讨转换过程中需要注意的关键点。 ## 一、BigDecimal简介 ### 1.1 BigDecimal的概念 BigDecimal是java.math包下的一个类,它提供了对不可变的、任意...
在Python中虽然没有直接对应的类,但理解`BigDecimal`的工作原理对于处理需要精确计算的场景是很有帮助的。本篇文章将详细探讨`BigDecimal`在加减乘除运算中的应用及其注意事项。 首先,`BigDecimal`对象的初始化有...
Java中的`BigDecimal`类是用来表示任意精度的十进制数,尤其适合于需要精确计算的商业和财务场景。它的核心概念包括非标度值(unscaled value)和标度(scale),非标度值是一个任意精度的整数,标度则是小数点后的...
在Java中,`double`类型是按照双精度浮点数标准来实现的,它有11位指数和53位尾数。尽管53位看似足够大,但在某些运算中,即使是简单的小数相加也可能因为精度损失而产生不预期的结果。例如,`0.1 + 0.2 != 0.3`在...
为了应对浮点数运算可能出现的精度问题,Java提供了`java.math`包,其中包含了一些用于精确数学计算的类,比如`BigDecimal`。本文将深入探讨Java中常用的数学类以及如何进行精确的浮点数运算,包括加减乘除、四舍五...