float 和 double 只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal。,而且使用 BigDecimal 类也可以进行大数的操作。具体参见 API
编号 | 方法 | 类型 | 描述 |
1 | public BigDecimal(double val) | 构造 | 将 double 表示形式转化为 BigDecimal |
2 | public BigDecimal(int val) | 构造 | 将 int 表示形式转化为 BigDecimal |
3 | public BigDecimal(String val) | 方法 | 将字符串表示形式转化为 BigDecimal |
4 | public BigDecimal add(BigDecimal augend) | 方法 | 加法 |
5 | public BigDecimal subtract(BigDecimal subtrahend) | 方法 | 减法 |
6 | public BigDecimal multiply(BigDecimal multiplicand) | 方法 | 乘法 |
7 | public BigDecimal divide(BigDecimal divisor) | 方法 | 除法 |
一、BigDecimal 的计算
- double d1 = 9.45;
- double d2 = 3.14;
- //使用BigDecimal(String val)构造方法
- BigDecimal b1 = new BigDecimal(Double.toString(d1));
- BigDecimal b2 = new BigDecimal(Double.toString(d2));
- //b1:9.45 ——b2:3.14
- System.out.println("b1:"+b1+"\t——b2:"+b2);
- //加法
- BigDecimal add = b1.add(b2);
- //加法:12.59
- System.out.println("加法:"+add);
- //减法
- BigDecimal sub = b1.subtract(b2);
- //减法:6.31
- System.out.println("减法:"+sub);
- //乘法
- BigDecimal mul = b1.multiply(b2);
- //乘法:29.6730
- System.out.println("乘法:"+mul);
- //除法
- int scale = 20;//保留20位小数
- BigDecimal div1 = b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP);
- //除法:3.0095541401273884
- System.out.println("除法:"+div1.doubleValue());
- //格式化
- double foo = 2334233.1415956;
- //获取常规数值格式
- NumberFormat number = NumberFormat.getNumberInstance();
- String str1 = number.format(foo);
- //获取常规数值格式:2,334,233.142
- System.out.println("获取常规数值格式:"+str1);
- //获取整数数值格式——返回当前缺省语言环境的通用数值格式
- NumberFormat integer = NumberFormat.getIntegerInstance();
- String inte1 = integer.format(foo);//如果带小数会四舍五入到整数12,343,172
- //获取整数数值格式:2,334,233
- System.out.println("获取整数数值格式:"+inte1);
- //获取货币数值格式——返回当前缺省语言环境的通用格式
- String curr = NumberFormat.getCurrencyInstance().format(foo);
- //获取货币数值格式:¥2,334,233.14
- System.out.println("获取货币数值格式:"+curr);
- //获取显示百分比的格式——返回当前缺省语言环境的百分比格式
- String percent = NumberFormat.getPercentInstance().format(foo);
- //获取显示百分比的格式:233,423,314%
- System.out.println("获取显示百分比的格式:"+percent);
- double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型 9 * 整型地方法适合于货币精度已知的情况,比如22.11+2.10转成2211+210计算,最后再/100,损失精度
二、常见问题
- double d3 = 0.1;
- //0.1000000000000000055511151231257827021181583404541015625
- System.out.println(new BigDecimal(d3).toString());
- //0.1
- System.out.println(new BigDecimal(d3+"").toString());
- //0.1
- System.out.println(new BigDecimal(Double.toString(d3)).toString());
- //0.1
- System.out.println(new BigDecimal(Double.toString(0.1000000000000000055511151231257827021181583404541015625)).toString());
第一个:事实上,由于二进制无法精确地表示十进制小数 0.1,但是编译器读到字符串 "0.1" 之后,必须把它转成 8 个字节的 double 值,因 此,编译器只能用一个最接近的值来代替 0.1 了
第二个:BigDecimal 能够正确地把字符串转化成真正精确的浮点数。
第三个:问题在于 Double.toString 会使用一定的精度来四舍五入 double,然后再输出
第四个:等价于第三行
结论:
1. 如果希望精确的表示希望的数值,一定使用字符串来表示
2. 使用 Double.toString 也不靠谱,参见第二行
来源: http://www.bubuko.com/infodetail-1949103.html