Tru*_* Ha 272 java floating-point double bigdecimal
我必须计算一些浮点变量,我的同事建议我使用BigDecimal而不是double因为它会更精确.但我想知道它是什么以及如何最大限度地利用它BigDecimal?
ext*_*eon 408
A BigDecimal是表示数字的精确方式.A Double具有一定的精度.使用各种大小的双精度(比如说d1=1000.0和d2=0.001)可能会导致在0.001求和时完全丢弃,因为幅度的差异是如此之大.有了BigDecimal这不会发生.
缺点BigDecimal是它速度较慢,并且以这种方式编程算法(由于+ - *而/不是过载)更加困难.
如果您正在处理金钱,或精确是必须的,请使用BigDecimal.否则Doubles往往足够好.
我建议阅读javadoc,BigDecimal因为他们解释的事情比我在这里做得更好:)
小智 156
我的英语不好,所以我在这里写一个简单的例子.
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);
Run Code Online (Sandbox Code Playgroud)
节目输出:
0.009999999999999998
0.01
Run Code Online (Sandbox Code Playgroud)
有人还想用双?;)
小智 47
与double有两个主要区别:
您应该使用BigDecimal进行货币计算的原因并不是它可以表示任何数字,而是它可以表示可以用十进制概念表示的所有数字,并且几乎包括货币世界中的所有数字(您永远不会转移1/3 $给某人).
Oli*_*bes 23
如果你写下一个小数值,如1 / 7十进制值,你得到
1/7 = 0.142857142857142857142857142857142857142857...
Run Code Online (Sandbox Code Playgroud)
无限的序列142857.由于您只能编写有限数量的数字,因此不可避免地会引入舍入(或截断)错误.
相似的数字1/10或1/100与小数部分表示为二进制数也具有小数点后的数字的无限数量:
1/10 = binary 0.0001100110011001100110011001100110...
Run Code Online (Sandbox Code Playgroud)
Doubles 将值存储为二进制,因此可能仅通过将十进制数转换为二进制数来引入错误,甚至不进行任何算术运算.
BigDecimal另一方面,十进制数字(如)按原样存储每个十进制数字.这意味着十进制类型在一般意义上不比二进制浮点或固定点类型更精确(例如,它不能在1/7不损失精度的情况下存储),但对于具有有限小数位数的数字,它更准确通常是钱计算的情况.
Java BigDecimal具有额外的优势,即它可以在小数点的两边具有任意(但有限)的数字位数,仅受可用内存的限制.
BigDecimal是Oracle的任意精度数值库.BigDecimal是Java语言的一部分,适用于从财务到科学的各种应用程序(这就是上下文).
将双打用于某些计算没有任何问题.但是,假设您想要计算Math.Pi*Math.Pi/6,即Riemann Zeta函数的值,实际参数为2(我正在研究的项目).浮点除法会给您带来一个圆角误差的痛苦问题.
另一方面,BigDecimal包含许多用于计算任意精度的表达式的选项.下面的Oracle文档中描述的add,multiply和divide方法在BigDecimal Java World中"取代"+,*和/:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
compareTo方法在while和for循环中特别有用.
但是,在使用BigDecimal的构造函数时要小心.在许多情况下,字符串构造函数非常有用.例如,代码
BigDecimal onethird = new BigDecimal("0.33333333333");
利用1/3的字符串表示来表示无限重复的数字到指定的准确度.舍入误差最有可能发生在JVM内部的某个深处,以致舍入误差不会干扰大多数实际计算.然而,从个人经验来看,我看到了四舍五入.从Oracle文档中可以看出,setScale方法在这些方面很重要.
如果要进行计算,则应遵循有关如何计算和应使用的精度的法律。如果失败,那将是非法行为。唯一的真实原因是十进制大小写的位表示不精确。就像罗勒简单地说的那样,一个例子是最好的解释。只是为了补充他的示例,发生了以下情况:
static void theDoubleProblem1() {
double d1 = 0.3;
double d2 = 0.2;
System.out.println("Double:\t 0,3 - 0,2 = " + (d1 - d2));
float f1 = 0.3f;
float f2 = 0.2f;
System.out.println("Float:\t 0,3 - 0,2 = " + (f1 - f2));
BigDecimal bd1 = new BigDecimal("0.3");
BigDecimal bd2 = new BigDecimal("0.2");
System.out.println("BigDec:\t 0,3 - 0,2 = " + (bd1.subtract(bd2)));
}
Run Code Online (Sandbox Code Playgroud)
输出:
Double: 0,3 - 0,2 = 0.09999999999999998
Float: 0,3 - 0,2 = 0.10000001
BigDec: 0,3 - 0,2 = 0.1
Run Code Online (Sandbox Code Playgroud)
我们还有:
static void theDoubleProblem2() {
double d1 = 10;
double d2 = 3;
System.out.println("Double:\t 10 / 3 = " + (d1 / d2));
float f1 = 10f;
float f2 = 3f;
System.out.println("Float:\t 10 / 3 = " + (f1 / f2));
// Exception!
BigDecimal bd3 = new BigDecimal("10");
BigDecimal bd4 = new BigDecimal("3");
System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4)));
}
Run Code Online (Sandbox Code Playgroud)
给我们输出:
Double: 10 / 3 = 3.3333333333333335
Float: 10 / 3 = 3.3333333
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion
Run Code Online (Sandbox Code Playgroud)
但:
static void theDoubleProblem2() {
BigDecimal bd3 = new BigDecimal("10");
BigDecimal bd4 = new BigDecimal("3");
System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4, 4, BigDecimal.ROUND_HALF_UP)));
}
Run Code Online (Sandbox Code Playgroud)
具有输出:
BigDec: 10 / 3 = 3.3333
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
275134 次 |
| 最近记录: |