金融项目关于金额的数据存储使用什么数据类型.
public class Test {
public static void main(String[] args) {
double a=0.03;
double b=0.02;
double c=a-b;
System.out.println(c);
}
}
# 输出结果为:
0.009999999999999998
因为float与double都是浮点数,想让float或者double精确地表示0.1(或者10的任何负数次方值)是不可能的,浮点数参与的运算通常伴随着因为无法精确表示而进行的近似或舍入,
所以导致结果会有丝毫的偏差,而涉及金额的计算是绝对不予许存在偏差的。
这种舍入错误产生的原因是浮点数实际上是用二进制系统实现的,而分数1/10在二进制系统中没有精确的表示,其道理就如同在十进制系统中无法精确表示1/3一样;再比如0.5在二进制系统中有精确表示,而0.55在二进制系统中没有精确表示。
在java中使用BigDecimal来解决.
当使用double进行商业运算时,double计算会丢失精度时。可以使用BigDecimal进行计算。
import java.math.BigDecimal;
import org.junit.Test;
public class TestBigDecimal{
@Test
public void test(){
double a=0.1;
double b=0.2;
System.out.println(a+b);
BigDecimal a1=new BigDecimal("0.1");
BigDecimal b1=new BigDecimal("0.2");
System.out.println(a1+b1);
BigDecimal c1=new BigDecimal("0.23574");
a1=a1.add(c1);
a1=a1.setScale(1,BigDecimal.ROUND_DOWN);
System.out.println(a1);
}
}
//输出结果如下:
0.30000000000000004
0.3
0.4
double的加减无法精确计算出0.3,而使用BigDecimal却可以。
当然,如果直接将double传给BigDecimal,不但无法解决精度问题,反而对精度进行了补全。所以,为确保精度,我们将String传给它。
设置精度
BigDecimal.setScale() // 方法用于格式化小数点
setScale(1) // 表示保留一位小数,默认用四舍五入方式
setScale(1,BigDecimal.ROUND_DOWN) // 直接删除多余的小数位,如2.35会变成2.3
setScale(1,BigDecimal.ROUND_UP) // 进位处理,2.35变成2.4
setScale(1,BigDecimal.ROUND_HALF_UP) // 四舍五入,2.35变成2.4
setScaler(1,BigDecimal.ROUND_HALF_DOWN) // 四舍五入,2.35变成2.3,如果是5则向下舍
.scale() 取精度值,即小数点后位数(注:BigDecimal可以通过setScale来提高精度,只要新设的值比原来的大!
BigDecimal也可以通过setScale来降低精度。因为新设的值比原来的小,所以必须保证原来数值的该位小数点后面都是0,只有这样才可以设比原来小的精度。
例:原来的值是:4.1235648,想把scale设为小于7为都会出错的,如果原来的值是:4.1235000,把scale设为小于4位会出错,而设为4、5、6、7都没有问题,设得更大,肯定不会出错)
加减乘除
add(BigDecimal) BigDecimal对象中的值相加,然后返回这个对象。
subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。
multiply(BigDecimal) BigDecimal对象中的值相乘,然后返回这个对象。
divide(BigDecimal) BigDecimal对象中的值相除,然后返回这个对象。
除法详解
BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
1. 除数
2. 保留精度
3. 舍入规则
BigDecimal.ROUND_DOWN // 直接删除多余的小数位,如2.35会变成2.3
BigDecimal.ROUND_UP // 进位处理,2.35变成2.4
BigDecimal.ROUND_HALF_UP // 四舍五入,2.35变成2.4
BigDecimal.ROUND_HALF_DOWN // 四舍五入,2.35变成2.3,如果是5则向下舍
BigDecimal mData = new BigDecimal("9.655").setScale(2, BigDecimal.ROUND_HALF_UP);
----结果:-----
mData=9.66
其他API
toString() 将BigDecimal对象的数值转换成字符串。
doubleValue() 将BigDecimal对象中的值以双精度数返回。
floatValue() 将BigDecimal对象中的值以单精度数返回。
longValue() 将BigDecimal对象中的值以长整数返回。
intValue() 将BigDecimal对象中的值以整数返回。