js存储原理

本文深入探讨了JavaScript中浮点数的二进制表示导致的精度丢失问题,以及如何通过BigInt类型来处理大整数,避免精度误差。同时介绍了BigInt的基本操作和限制,以及在Number.MAX_SAFE_INTEGER范围外的数值计算需求。
摘要由CSDN通过智能技术生成

引子

let a = 1
let b = 0
let c = -1
// 转为二进制
a.toString(2) // 1 
b.toString(2) // 0
c.toString(2) // -1

0.1 + 0.2 // 0.30000000000000004

let x = 0.1
let y = 0.2
let s = 0.3
x.toString(2)           // 0.0001100110011001100110011001100110011001100110011001101
y.toString(2)           // 0.001100110011001100110011001100110011001100110011001101
s.toString(2)           // 0.010011001100110011001100110011001100110011001100110011
(0.1 + 0.2).toString(2) // 0.0100110011001100110011001100110011001100110011001101

计算机中所有数据都是二进制存储,计算时,先是二进制计算,再转为十进制。
上面二进制计算时,发生了精度丢失。

js对二进制小数的存储方式-64位双精度存储

二进制表示法
  1. 符号位
  2. 指数位
  3. 尾数位

双精度: 符号1, 指数11,尾数52,总位数64。
符号位:标识正负,值为0或1
指数位:科学计数法的指数
尾数位:科学计数法后的有效数字

// 存储大概如此,从右到左。
|63|62-52|51-0|
|符号位|指数位|尾数位|
科学计数法

为了节省存储空间,在计算机中是以科学计数法表示。

// 十进制的科学计数法
1100 => 11 X 102 // 102其实是10的2次方,即10^2
// 二进制
1.1001100110011001100110011001100110011001100110011001... X 2-4 // 2^-4
精度丢失

二进制字符串,实际是计算机存储的尾数位
位数不够,怎么切割?

有效数字第53位及以后的数字是不能存储的,它遵循,如果是1就向前一位进1,如果是0就舍弃的原则

  • 0.1 的存储
0.1
// 原本:
0.00011001100110011001100110011001100110011001100110011001...
// 科学计数法尾数位:
1.1001100110011001100110011001100110011001100110011001...
// 切割后:
0.0001100110011001100110011001100110011001100110011001101

这导致了精度丢失。

  • 再看0.1 + 0.2
0.1 + 0.2
0.0100110011001100110011001100110011001100110011001100111
实际上这个结果的有效数字已经超过了 52位,我们要从末尾进行 10舍得到下面的结果
0.0100110011001100110011001100110011001100110011001101

JavaScript能表示的最大数字

由与 IEEE754双精度64位规范的限制:

指数位能表示的最大数字: 1023(十进制)

尾数位能表达的最大数字即尾数位都位 1的情况

所以JavaScript能表示的最大数字即位

1.111…X 21023(2^1023) 这个结果转换成十进制是 1.7976931348623157e+308,这个结果即为 Number.MAX_VALUE

最大安全数字

JavaScript中 Number.MAX_SAFE_INTEGER表示最大安全数字,计算结果是 9007199254740991,
即在这个数范围内不会出现精度丢失(小数除外),这个数实际上是 1.111…X 252(2^52)。

相关库

解决精度丢失的库:

  1. number-precision
  2. mathjs

开源库来处理大整数:

  1. node-bignum
  2. node-bigint

es10, bitInt类型

第七种原始类型
js七种原始类型:number, string, null, undefined, boolean, Symbol, bitInt
在过去,不支持大于 9007199254740992 的整数值。如果超过,该值将锁定为 MAX_SAFE_INTEGER+1:
BigInt 是一个任意精度的整数。可以计算最大安全整数以上的数字。

定义

const a = 1n;
const b = BitInt(9007199254740991)

不能用于 Math 对象中的方法
不能和任何 Number 实例混合运算,两者必须转换成同一种类型。
BigInt 变量在转换成 Number 变量时可能会丢失精度。

以下操作符可以和 BigInt 一起使用: +、*-**%
>>> (无符号右移)之外的 位操作 也可以支持。
因为 BigInt 都是有符号的, >>> (无符号右移)不能用于 BigInt。
为了兼容 asm.js ,BigInt 不支持单目 (+) 运算符。

小数部分不会返回,导致结果/是取整。
Number 和 BigInt 可以进行比较。(适合数值比较小时)

转化:由于在 Number 与 BigInt 之间进行转换会损失精度,因而建议仅在值可能大于253 时使用 BigInt 类型,并且不在两种类型之间进行相互转换。

其实说白了,就是加了个n,然后数字不限了。
操作符基本和数字一样,除了不能使用无符号右移。
/会被取整。
值可能大于253 时使用 BigInt 类型,并且不在两种类型之间进行相互转换

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值