Android价格精度问题

简介

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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值