谜题2:找零时刻

本文探讨了在货币计算中使用浮点数(如float和double)导致的精度问题,通过具体例子展示了1.1和1.25在二进制表示上的差异,以及这些差异如何影响计算结果。文章进一步解释了为什么某些十进制小数无法在二进制中精确表示,并提出了使用BigDecimal类来解决此类问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

谜题2:找零时刻

1、有一张2元的钞票,买了一个价值1.10元的物品,那么应该找给他多少钱呢?

package chapter.one;

import java.math.BigDecimal;

/**
 * @author Nass
 * @date 2019/11/13 19:30
 */
public class Change {
    public static void main(String[] args) {
        System.out.println(2.00-1.10);
      	System.out.println(2.00-1.25);
    }
}

运行结果:

0.8999999999999999
0.75

显然这和我们想要的结果(0.90)是不一致的。

原因

1.1(十进制) = 1.0001100110011001(二进制) 超出计算精度,结果保留十六位小数

​ 1.10 = 20+1/(24) + 1/(2^5) + 1/(2^8) + …

​ 其中1.1只能无限循环下去,这就意味着0.1在计算机中不能被精确表示

1.25(十进制) = 1.01(二进制)

​ 1.25 = 20+1/(22)

​ 1.25可以在计算机中精确表示

并不是所有的小数都可以用二进制浮点数精确表示:

二进制浮点对于货币计算是非常不适合的,因为它不可能将0.1或者10的其它任何次负幂——精确表示为一个长度有限的二进制小数


2、解决方法

使用BigDecimal:

一定要用BigDecimal(String)构造器,千万不要用BigDecimal(double)构造器

BigDecimal a = new BigDecimal("2.00");
System.out.println(a);
BigDecimal b = new BigDecimal(1.10);
System.out.println(b);

BigDecimal result = new BigDecimal("2.00").subtract(new BigDecimal("1.10"))
System.out.println(result);

运行结果:

2.00
1.100000000000000088817841970012523233890533447265625
result = 0.90

3、警示⚠️

在需要精确答案的地方,要避免使用float和double;对于货币计算,要使用int、long、BigDecimal。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值