los*_*ney 5 java double bigdecimal
我知道double/float的问题,建议使用BigDecimal而不是double/float来表示货币字段.但是双/浮动更有效且节省空间.然后我的问题是:使用double/float来表示Java类中的货币字段是可以接受的,但是使用BigDecimal来处理算术(即在任何算术之前将double/float转换为BigDecimal)和等同检查?
原因是节省了一些空间.我真的看到很多项目正在使用double/float来代表货币领域.
这有什么陷阱吗?提前致谢.
不,你不能.
假设double
足以存储两个值x
和y
.然后你将它们转换为安全BigDecimal
和多个.结果是准确的,但是如果将乘法结果存回double
,很可能会失去精度.证明:
double x = 1234567891234.0;
double y = 1234567891234.0;
System.out.println(x);
System.out.println(y);
BigDecimal bigZ = new BigDecimal(x).multiply(new BigDecimal(y));
double z = bigZ.doubleValue();
System.out.println(bigZ);
System.out.println(z);
Run Code Online (Sandbox Code Playgroud)
结果:
1.234567891234E12 //precise 'x'
1.234567891234E12 //precise 'y'
1524157878065965654042756 //precise 'x * y'
1.5241578780659657E24 //loosing precision
Run Code Online (Sandbox Code Playgroud)
x
并且y
准确,以及使用乘法BigDecimal
.然而,在回到double
我们松散的最低有效数字后.
我还建议您只使用BigDecimal进行可能涉及货币的所有算术.
确保始终使用BigDecimal的String构造函数.为什么?在JUnit测试中尝试以下代码:
assertEquals(new BigDecimal("0.01").toString(), new BigDecimal(0.01).toString());
Run Code Online (Sandbox Code Playgroud)
您将获得以下输出:
expected:<0.01[]> but was <0.01[000000000000000020816681711721685132943093776702880859375]>
Run Code Online (Sandbox Code Playgroud)
事实是,你不能完全存储0.01作为'双倍'数量.只有BigDecimal的存储您所需要的数量EXACTLY只要你想它.
请记住,BigDecimal是不可变的.以下将编译:
BigDecimal amount = new BigDecimal("123.45");
BigDecimal more = new BigDecimal("12.34");
amount.add(more);
System.out.println("Amount is now: " + amount);
Run Code Online (Sandbox Code Playgroud)
但结果输出将是:
金额现在是:123.45
那是因为你需要将结果分配给一个新的(或相同的)BigDecimal变量.
换一种说法:
amount = amount.add(more)
Run Code Online (Sandbox Code Playgroud)