BigInt数据类型--JS的精度有限问题

JavaScript 所有数字都保存成 64 位浮点数,这给数值的表示带来了两大限制。

一是数值的精度只能到 53 个二进制位(相当于 16 个十进制位),大于这个范围的整数,JavaScript 是无法精确表示,这使得 JavaScript 不适合进行科学和金融方面的精确计算。

二是大于或等于2的1024次方的数值,JavaScript 无法表示,会返回Infinity。

// 超过 53 个二进制位的数值,无法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true

// 超过 2 的 1024 次方的数值,无法表示
Math.pow(2, 1024) // Infinity

问题场景:JSON.parse中遇到的BIGINT

比较常见的场景为后台返回了一串JSON但是数字为BIGINT导致解析错误,一般为16位

var c='{"num": 90071992547409999}'
JSON.parse(c) // {num: 90071992547410000}

解决办法:

JavaScript 中的 Number 是双精度浮点型,这意味着精度有限。

Number.MAX_SAFE_INTEGER 就是安全范围内的最大值,为 2**53-1。

最小安全值为 Number.MIN_SAFE_INTEGER 值为 -((2**53)-1)。

超出安全值的计算都会丧失精度。

如下,可以看到 max + 1 与 max + 2 的值相同,这显然是不对的。

const max = Number.MAX_SAFE_INTEGER; // 9007199254740991
max + 1 // 9007199254740992
max + 2 // 9007199254740992

ECMAScript 中的提案 BigInt 就是一个可以表示任意精度的新的数字原始类型

BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。

为了与 Number 类型区别,BigInt 类型的数据必须添加后缀n。

1234 // 普通整数
1234n // BigInt

// BigInt 的运算
1n + 2n // 3n

JavaScript 原生提供BigInt函数,可以用它生成 BigInt 类型的数值。

转换规则基本与Number()一致,将其他类型的值转为 BigInt。

BigInt(123) // 123n
BigInt('123') // 123n
BigInt(false) // 0n
BigInt(true) // 1n
const a = 2172141653n;
const b = 15346349309n;

// BigInt 可以保持精度
a * b // 33334444555566667777n

// 普通整数无法保持精度
Number(a) * Number(b) // 33334444555566670000

题目练习:

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入:digits = [1,2,3] 输出:[1,2,4] 解释:输入数组表示数字 123。

var plusOne = function(digits) {
  //    let number = 0
  //     for(let i = 0;i<=digits.length-1;i++){
  //         number += digits[i] * (10 ** (digits.length-i-1))
  //     }
  //     return [...(number+1).toString()]
	// 存在精度问题,所以此方法行不通
  // 输入:
  // [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]
  // 输出:
  // [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,0,0,0]
  // 预期结果:
  // [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,4]
  
  let num=BigInt(digits.join(''))+1n
  return num.toString().split('')

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值