javascript中的计算精度问题

以前知道计算机中存在计算精度的问题,但是没仔细探讨过。今天在javascript中见到0.1+0.2,输出不是预期的0.3,便想深入了解一下这个问题。

console.log(0.1+0.2);  //0.30000000000000004

在控制台输出0.1+0.2,会发现结果不是0.3,而是0.30000000000000004。这是什么原因造成的呢?这涉及到计算机科学中的一个基本概念,即浮点数的二进制表示和有限精度运算。

浮点数的二进制表示

在计算机中,浮点数(包括小数)通常是以二进制形式存储的。然而,与十进制数不同,不是所有的十进制小数都能精确地转换为二进制浮点数。这是因为二进制浮点数的表示方式是基于2的幂次的,而像0.1和0.2这样的十进制小数在转换为二进制时会出现无限循环小数。
例如,0.1在二进制中是一个无限循环小数,它近似于:

0.1 = 0.00011001100110011001100110011001100110011001... (二进制)
0.2 = 0.00110011001100110011001100110011001100110011... (二进制)

有限精度运算

由于计算机存储浮点数的位数是有限的(通常是32位或64位的浮点数),因此这些无限循环小数在存储时会被截断,导致存储的值与原始值略有不同。这种截断或近似存储导致了浮点运算时的精度损失。

当进行0.1 + 0.2的运算时,计算机实际上是在对这两个近似存储的二进制浮点数进行加法运算。由于这两个数本身就不完全精确,它们的和也不会完全精确,而是会接近于0.3但带有一些微小的误差,也就是我们看到的0.30000000000000004。
以下是一些常见的例子:

加法运算:
0.1 + 0.7:结果是0.7999999999999999,而不是预期的0.8。
0.2 + 0.4:结果是0.6000000000000001,而不是预期的0.6。

减法运算:
1.6 - 1.3:结果是0.30000000000000004,而不是预期的0.3。
0.3 - 0.2:结果是0.09999999999999998,而不是预期的0.1。

乘法运算:
0.7 * 180:结果是125.99999999999999,而不是预期的126。
9.7 * 100:结果是969.9999999999999,而不是预期的970。

除法运算:
0.3 / 0.1:结果是2.9999999999999996,而不是预期的3。
0.69 / 10:结果是0.06899999999999999,而不是预期的0.069。

解决方案

虽然这种浮点运算的误差在大多数情况下是可以忽略不计的,但在某些需要高精度的场合(如金融计算)中,这种误差可能会累积并变得显著。为了解决这个问题,可以采取以下几种方法:

1.使用整数运算:将小数转换为整数进行运算,然后再将结果转换回小数。例如,可以将所有的金额都乘以100(转换为分),进行整数运算后再除以100。
示例:计算商品总价
假如我们需要计算几种商品的总价,每种商品的价格都以元为单位(如人民币)。为了避免浮点数运算的精度问题,我们可以将所有的价格乘以100(转换为分),进行整数运算后再除以100(转换回元)。
商品价格(以元为单位):
商品A:19.99元
商品B:29.55元
商品C:4.99元
转换为分(乘以100):
商品A:1999分
商品B:2955分
商品C:499分
整数运算:
计算总价(以分为单位):
1999+2955+499=5453分
将总价转换回元(除以100):
5453/100=54.53元
2.使用高精度库:使用像BigInt(用于大整数)或第三方高精度数学库(如decimal.js、big.js等)来处理需要高精度的浮点运算。
3.四舍五入:在显示结果时,使用四舍五入等方法来隐藏微小的误差。例如,可以使用toFixed()方法将结果四舍五入到指定的小数位数。

console.log((0.1+0.2).toFixed(2));  //0.30

精度问题不是JavaScript独有的问题,而是几乎所有使用有限位数来表示浮点数的编程语言都会遇到的问题,包括C、C++、Python、Java等。通过这些方法,可以在需要时减少或消除浮点运算的误差。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值