文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

利用Math.js解决JS计算小数精度丢失问题

2024-04-02 19:55

关注

缘由

最近在做公司的一个点餐H5项目需要前端动态计算用户选的商品的总价(单价*数量)和购物车的总价格时发现关于 JavaScript 浮点数计算精度不准确问题。在控制台输入0.1+0.2也能发现此问题。

    // 加法
    0.1 + 0.2 = 0.30000000000000004
    0.7 + 0.1 = 0.7999999999999999
    0.2 + 0.4 = 0.6000000000000001

    // 减法
    1.5 - 1.2 = 0.30000000000000004
    0.3 - 0.2 = 0.09999999999999998
    
    // 乘法
    19.9 * 100 = 1989.9999999999998
    0.8 * 3 = 2.4000000000000004
    35.41 * 100 = 3540.9999999999995

    // 除法
    0.3 / 0.1 = 2.9999999999999996
    0.69 / 10 = 0.06899999999999999

问题的原因

为什么 0.1+0.2 JS加不了? 产生浮点数计算精度不准确的原因: 在计算机角度,计算机算的是二进制,而不是十进制。二进制后变成了无线不循环的数,而计算机可支持浮点数的小数部分可支持到52位,所有两者相加,在转换成十进制,得到的数就不准确了,加减乘除运算原理一样。

十进制二进制
0.10.0001 1001 1001 1001 ...
0.20.0011 0011 0011 0011 ...
0.30.0100 1100 1100 1100 ...
0.40.0110 0110 0110 0110 ...
0.50.1
0.60.1001 1001 1001 1001 ...

所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。

最通俗的解释

比如一个数 1÷3=0.33333333...... 大家都知道3会一直无限循环,数学可以表示,但是计算机要存储,方便下次取出来再使用,但0.333333...... 这个数 无限循环,你让计算机怎么存储?计算机再大的内存它也存不下,对吧! 所以不能存储一个相对于数学来说的值,只能存储一个近似值,所以当计算机存储后再取出来用时就会出现精度问题。

解决方案 - Math.js

对于任意精度的计算,math.js 支持BigNumber 数据类型。

安装

npm install mathjs

请注意,在 TypeScript 项目中使用 mathjs 时,您还必须安装类型定义文件:npm install @types/mathjs.

封装

import * as math from 'mathjs';
export default {
    // 加
	add(num1,num2){
		return math.add(math.bignumber(num1),math.bignumber(num2));
	},
	// 乘
	multiply(num1,num2){
		return math.multiply(math.bignumber(num1),math.bignumber(num2));
	},
	// 减
	subtract(num1,num2){
		return math.subtract(math.bignumber(num1),math.bignumber(num2));
	},
	// 除
	divide(num1,num2){
		return math.divide(math.bignumber(num1),math.bignumber(num2));
	}
}

使用

import math from './math.js'
let addNum = math.add(3,2); // 5
let mulNum = math.multiply(3,2); // 6
let subNum = math.subtract(3,2); // 1 
let divNum = math.divide(3,2); // 1.5

附:math.js 大数功能

<script type="text/javascript">
// functions and constants
console.log('mathjs BigNumber eg')
print(math.add(math.bignumber(0.1), math.bignumber(0.2))) // 加法 BigNumber, 0.3
print(math.subtract(math.bignumber(1), math.bignumber(0.9))) // 减法 BigNumber, 0.1
print(math.multiply(math.bignumber(4.10), math.bignumber(100))) // 乘法 BigNumber, 0.1
print(math.ceil(math.bignumber(6.10)/ math.bignumber(0.1)));   //除法 向上取整 61
print(math.floor(math.bignumber(6.10)/ math.bignumber(0.1)));   //除法 向下取整 61
print(math.round(math.bignumber(6.10)/ math.bignumber(0.1)));   // 除法 四舍五入 61

function print (value) {
  const precision = 14
  console.log(math.format(value, precision))
}
</script>

总结

到此这篇关于利用Math.js解决JS计算小数精度丢失问题的文章就介绍到这了,更多相关JS计算小数精度丢失内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯