我必须计算一些浮点变量,我的同事建议我使用BigDecimal而不是double,因为它会更精确。但我想知道它是什么,以及如何最大限度地利用BigDecimal?
当前回答
BigDecimal是Oracle的任意精度数值库。BigDecimal是Java语言的一部分,对于从金融到科学的各种应用程序都很有用。
在某些计算中使用double并没有错。但是,假设您想计算数学。π *数学。Pi / 6,也就是黎曼ζ函数实参为2的值(我目前正在做的一个项目)。浮点除法给你带来了一个令人痛苦的舍入误差问题。
另一方面,BigDecimal包含许多用于将表达式计算到任意精度的选项。下面Oracle文档中描述的加、乘、除方法在BigDecimal Java World中“取代”+、*和/:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
compareTo方法在while和for循环中特别有用。
但是,在使用BigDecimal的构造函数时要小心。字符串构造函数在很多情况下非常有用。例如,代码
BigDecimal 三分之一 = 新的 BigDecimal(“0.33333333333”);
利用1/3的字符串表示形式,以指定的精度表示无限重复的数字。舍入错误很可能位于JVM内部的某个深处,因此舍入错误不会影响大多数实际计算。然而,从个人经验来看,我看到四舍五入逐渐增多。从Oracle文档中可以看出,setScale方法在这些方面很重要。
其他回答
如果需要在算术中使用除法,则需要使用double而不是BigDecimal。BigDecimal中的除法(divide(BigDecimal)方法)是非常无用的,因为BigDecimal不能处理重复的十进制有理数(除法在除数所在的位置,并且会抛出java.lang. arithmayexception:非终止十进制展开;没有精确可表示的十进制结果。
试试BigDecimal.ONE吧。把(新BigDecimal (3));
另一方面,Double可以很好地处理除法(可以理解的精度大约是15位有效数字)
如果你把1 / 7这样的小数写成小数,你会得到
1/7 = 0.142857142857142857142857142857142857142857...
用无限重复的数字142857。由于您只能写入有限数量的数字,因此不可避免地会引入舍入(或截断)错误。
像1/10或1/100这样的数字表示为带小数部分的二进制数,小数点后也有无限位数:
1/10 = binary 0.0001100110011001100110011001100110...
double将值存储为二进制,因此仅通过将十进制数转换为二进制数可能会引入错误,甚至不做任何算术。
另一方面,十进制数字(如BigDecimal)按原样存储每个十进制数字(二进制编码,但每个小数单独存储)。这意味着在一般意义上,十进制类型并不比二进制浮点或定点类型更精确(即,它不能在不损失精度的情况下存储1/7),但对于具有有限位数的十进制数字(通常用于金钱计算),它更准确。
Java的BigDecimal还有一个额外的优点,它可以在小数点的两边有任意(但有限的)位数,仅受可用内存的限制。
我的英语不好,所以我在这里只写一个简单的例子。
double a = 0.02;
double b = 0.03;
double c = b - a;
System.out.println(c);
BigDecimal _a = new BigDecimal("0.02");
BigDecimal _b = new BigDecimal("0.03");
BigDecimal _c = _b.subtract(_a);
System.out.println(_c);
项目输出:
0.009999999999999998
0.01
还有人想用double吗?;)
BigDecimal是Oracle的任意精度数值库。BigDecimal是Java语言的一部分,对于从金融到科学的各种应用程序都很有用。
在某些计算中使用double并没有错。但是,假设您想计算数学。π *数学。Pi / 6,也就是黎曼ζ函数实参为2的值(我目前正在做的一个项目)。浮点除法给你带来了一个令人痛苦的舍入误差问题。
另一方面,BigDecimal包含许多用于将表达式计算到任意精度的选项。下面Oracle文档中描述的加、乘、除方法在BigDecimal Java World中“取代”+、*和/:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
compareTo方法在while和for循环中特别有用。
但是,在使用BigDecimal的构造函数时要小心。字符串构造函数在很多情况下非常有用。例如,代码
BigDecimal 三分之一 = 新的 BigDecimal(“0.33333333333”);
利用1/3的字符串表示形式,以指定的精度表示无限重复的数字。舍入错误很可能位于JVM内部的某个深处,因此舍入错误不会影响大多数实际计算。然而,从个人经验来看,我看到四舍五入逐渐增多。从Oracle文档中可以看出,setScale方法在这些方面很重要。
它与double有两个主要区别:
任意精度,与BigInteger类似,它们可以包含任意精度和大小的数量(而double具有固定的位数) BigDecimal以10为底,而不是以2为底,BigDecimal是n*10^-scale,其中n是任意的有符号大整数,刻度可以被认为是小数点向左或向右移动的位数
说BigDecimal可以表示任何数字仍然是不正确的。但是你应该使用BigDecimal进行货币计算的两个原因是:
它可以表示所有可以用十进制表示的数字,包括货币世界中几乎所有的数字(你永远不会把1/3美元转给某人)。 精度可控制,避免累积误差。对于double,随着值的大小增加,其精度降低,这可能会在结果中引入重大误差。
推荐文章
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- Mockito.any()传递带有泛型的接口
- 在IntelliJ 10.5中运行测试时,出现“NoSuchMethodError: org.hamcrest. matcher . descripbemismatch”
- 使用String.split()和多个分隔符
- Java数组有最大大小吗?
- 在Android中将字符串转换为Uri
- 从JSON生成Java类?
- 为什么java.util.Set没有get(int index)?
- Swing和AWT的区别是什么?
- 为什么Java流是一次性的?
- 四舍五入BigDecimal *总是*有两位小数点后
- 设计模式:工厂vs工厂方法vs抽象工厂
- Java:检查enum是否包含给定的字符串?
- 它的意思是:序列化类没有声明一个静态的最终serialVersionUID字段?