版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013564742/article/details/82191172
简介
Android开发一般使用double类型来表示小数,如表示价格等,一般在要求不高的场景中使用是没有问题的,但是当double涉及到类型转换或者运算时是会有精度问题的。
例如用double来表示商品价格,如设置的价格16.9元,一般为了更好地扩展会设置一个折扣值,当没有折扣时实际价格=16.9 * 1.0(折扣,8折为0.8)。这在显示端是没有问题的。但是由于金额支付时接口一般是以分为单位的,且网络请求中一般不使用浮点数传输,因此需要把实际价格变为分,这个看着也简单,把结果乘以100就可以了。这就变成了实际请求金额=(int)(16.9 * 1.0 * 100)。如以下写法:
double price = 16.9;
int realPrice = (int)(price * 1.0 * 100);
System.out.println(realPrice);
这时问题就出来了,你会发现打印出来的结果是1689而不是1690。如果真按这个数值去扣款,每一个订单就要少扣一分钱,假如有10万个单就要损失1000块钱。这对商家来说是万万不能接受的。为什么会出现这种问题呢?
这是因为double在运算时丢失了精度造成的。
解决方法
1、可以使用float来表示价格,使用float运算时就不会有这个精度问题,但是java是不推荐使用float类型的。
float price = 16.9f;
int realPrice = (int)((price * 1.0f) * 100); // 注意凡是不在小数后加f的都是默认double类型,且结果都是转为double类型
System.out.println(realPrice);
2、使用Math.round方法将结果强行四舍五入再转为int类型,该方法暂时能当前解决问题,但是四舍五入不知道会出什么问题。
double price = 16.9;
int realPrice = (int)(Math.round(price * 1.0 * 100));
System.out.println(realPrice);
3、一个简单点的,由于价格精确2位小数,那么我们将结果加上0.005(比精度多一位,在原数值加上0.005能保证结果比期待结果小时能进位保持精度位不变,结果比期待结果大时不进位直接丢弃也没影响),再把多余的丢掉就可以保证了。(推荐这种方式)
double price = 16.9;
int realPrice = (int)((price * 1.0 + 0.005) * 100);
System.out.println(realPrice);