float与double精度丢失问题

解决一个价格转换显示的bug
double a=Double.parseDouble(3.80);
long price=new Double(a*100).longValue();
结果是3.799999999.......
大部分程序员都知道浮点类型不能用来做精确表示和运算,对根本原因能随口说来的可能并不多,借着这次机会,把涉及到计算机原理的知识点剖析下。
出现上述结果的根本原因是计算机使用二进制01无法准确表示某些带小数位的十进制数据
十进制数据转换成二进制数据,需经过如下计算:
1、整数部分
用该整数连续除以2,取余数,商再除以2,直到商等于0为止,最后把得到的余数按相反的顺序排列,即“除2取余法”
2、小数部分
小数部分“乘2取整,顺序排列”法,小数部分乘以2,从乘积中取整数部分,剩余的小数部分乘以2,
再把乘积的整部部分取出,剩余的小数部分乘以2,直到乘积中的小数部分为0或达到所要求的精度为止,把取出的整数部分顺序排列,即“乘2取整法”。
3、相加
最后把整数部分和小数部分相加,得到二进制数据
例如:十进制的3.8转换成二进制数值,步骤如下:
3(整数部分)
3/2=1................1
1/2=0.................1
十进制3 转换为二进制 11
0.8(小数部分)
0.8*2=1.6................1
0.6*2=1.2.................1
0.2*2=0.4.................0
0.4*2=0.8.................0
0.8*2=1.6................1
....
十进制0.8 转换为二进制 (0.11001100.....) 后边无限循环1100这段二进制数值,因此也就出现了上述的3.799999的情况。

java 的浮点类型都依据 IEEE 754 标准。IEEE 754 定义了32 位和 64 位双精度两种浮点二进制小数标准。
IEEE 754 用科学记数法以底数为 2 的小数来表示浮点数。32 位浮点数用 1 位表示数字的符号,用 8 位来表示指数,用 23位来表示尾数,即小数部分。作为有符号整数的指数可以有正负之分。小数部分用二进制(底数 2 )小数来表示。对于64位双精度浮点数,用 1 位表示数字的符号,用 11 位表示指数,52 位表示尾数。
在 IEEE 754 的 double 没有办法表示出 0.8,只能得到一个近似值。
float和double只能用来做科学计算或者是工程计算,在商业计算等精确计算中,用java.math.BigDecimal。
BigDecimal的解决方案就是,不使用二进制,而是使用十进制(BigInteger)+小数点位置(scale)来表示小数。
上述的39.8=398  * 0.1^1 这种表示方式下,避免了小数的出现,就不会有精度问题了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值