一篇文章带您了解如何高效解决JavaScript计算精度出现误差的问题

一篇文章带您了解如何解决js计算精度误差


一、为什么JavaScript在计算中会出现精度误差

前言

其实在计算中经常会出现一些奇怪的现象,当我们使用JavaScript来计算 0.1 + 0.2,它得到的结果并不是我们期待的0.3,而是 0.30000000000000004

JavaScript计算

当然,如果你把它作为条件判断语句,你会发现一个和你想象中完全不一样的结果

js计算条件判断语句

这是究竟为什么呢?

其实在JavaScript中,计算可能出现误差的原因通常是由于浮点数的精度问题。JavaScript 中的Number类型采用IEEE 754标准来表示浮点数,这个标准定义的是双精度浮点数,它能够表示的数值范围非常广泛,而这个标准在处理一些特别大或特别小的数时会出现舍入错误,所以计算机无法准确表示的小数有 0.1、0.2 或 0.3 这样的数字,因为它使用的是二进制浮点格式

例如,当你尝试表示分数1/3时,由于3不是2的幂次方,JavaScript 无法精确地用双精度浮点数表示这个数值,结果会有舍入误差。

注:其实在很多编程语言,比如 C、C++、JavaScript 、Python、Java、Ruby 等,都会出现这个问题。

二、出现精度误差的原因

在JavaScript中的所有数字,无论是整数还是小数,都是以64位浮点数(double)形式存储。

浮点数的表示包括三部分:

  • 符号位(Sign):0表示正数,1表示负数。
  • 指数位(Exponent): r用科学计数法表示时的指数部分,即2的幂次方。
  • 尾数位(Mantissa): r用科学计数法表示时的尾数部分。

浮点数的计算过程大致为:

  1. 先将两个浮点数转换成同一个表示形式(即同一个指数)。
  2. 将两个数的尾数相加。
  3. 处理可能出现的溢出和下溢情况。

背后的原理

其实在我们日常生活中通常使用10进制来进行计算,我们会发现当10除以2或者5的倍数时才可以被精确的表示,例如1/2、1/4、1/5、1/8 和 1/10等。因为2和5是10的质因数。但是 1/3、1/6 和 1/7 则是无限循环的小数。

同理,在计算机系统中使用的是二进制。只有一个分数使用基数2的质因数来表示时,它才可以被精确地表示,因为2是2的唯一质因数

当我们尝试表示像 0.1 这样的十进制小数时,计算机会使用一个近似值。这个近似值是通过将无限循环的二进制小数转换为有限位数的浮点数表示来实现的。

因此,当我们在计算机中进行浮点数运算时,结果可能会有微小的误差。

例如,0.1 在二进制中的近似表示可能是 0.000110011001100…,但在计算机的浮点数表示中,它可能被截断或舍入为 0.00011001100110,这就导致了 0.1 + 0.2 在计算机中可能不等于 0.3,而是略微有所偏差。

三、如何解决JavaScript计算精度误差

  1. 避免浮点数计算,或者尽可能使用整数来进行计算,以下是一个简单的函数,用于加0.1和减0.1,确保精度。
function addOrSubtract(value: number, increment: number, precision: number) {
  const factor = Math.pow(10, precision);
  const newValue =
    (Math.round(value * factor) + Math.round(increment * factor)) / factor;
  return newValue;
}

// 使用示例
let num = 0.1;
num = addOrSubtract(num, 0.1, 1); // 加0.1
console.log(num); // 输出: 0.2

num = addOrSubtract(num, -0.1, 1); // 减0.1
console.log(num); // 输出: 0.1

这个函数通过precision参数指定需要保留的小数位数,内部先将数值和增量乘以precision位的因子(即10的precision次幂),进行整数运算后再除以相同的因子,以还原到正确的小数位数。

  1. 使用库,如decimal.js或bignumber.js。
// 使用npm安装
npm install decimal.js
// 在HTML中引入
<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/10.2.0/decimal.min.js"></script>
// 引入Decimal构造函数
const Decimal = decimal.Decimal;

// 创建两个Decimal对象
let a = new Decimal('0.1');
let b = new Decimal('0.2');

// 进行加法运算
let sum = a.plus(b);

// 输出结果
console.log(sum.toString()); // 输出: 0.3
  1. 使用toFixed()方法可以将数字格式化为指定小数位数的字符串,但这并不会改变数值本身,只是在显示时控制小数位数。
let sum = 0.1 + 0.2;
console.log(sum.toFixed(2)); // 输出: 0.3

总结

在我们的日常开发中,对于金融相关的计算,要特别注意。尽量使用整数,并在最后转换为小数进行展示。或者使用一些提供了处理大数和高精度计算的工具的库,来减少或消除浮点数计算的误差。

  • 40
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
在Vue中解决JavaScript计算精度问题,可以使用第三方库math.js。通过引入math.js库,我们可以避免在浮点数计算中出现的精度问题。 在Vue中使用math.js可以按照以下步骤进行: 1. 首先,安装math.js库。可以使用npm或者yarn进行安装,例如:`npm install mathjs`。 2. 在Vue组件中引入math.js库,可以使用import语句进行引入,例如:`import math from 'mathjs'`。 3. 在需要进行计算的地方,使用math.js提供的相应方法进行计算。例如,对于减法,可以使用`math.subtract()`方法,对于加法,可以使用`math.add()`方法,对于除法,可以使用`math.divide()`方法。 4. 由于math.js处理的是大整数和大浮点数,所以在进行计算之前,需要将需要计算的数字转换成math.js支持的格式。可以使用`math.bignumber()`方法将数字转换成math.js支持的格式。 5. 最后,使用`math.format()`方法将计算结果转换成字符串格式,以避免出现科学计数法或多余的小数位。 举例来说,如果要解决0.1 + 0.2的计算精度问题,可以按照以下代码进行操作: ```javascript import math from 'mathjs' const addNumber = math.format(math.add(math.bignumber(0.1), math.bignumber(0.2))) console.log(addNumber) // 输出0.3 ``` 使用类似的方法,可以解决减法和除法的计算精度问题。请记住,在进行计算之前,将需要计算的数字转换成math.js支持的格式,然后使用相应的数学方法进行计算,并最后使用`math.format()`方法转换结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [vue使用mathjs解决前端计算精度不足问题](https://blog.csdn.net/qq_43555948/article/details/119885043)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT_Yu123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值