Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重学js —— js数据类型:BigInt #97

Open
lizhongzhen11 opened this issue Apr 12, 2020 · 0 comments
Open

重学js —— js数据类型:BigInt #97

lizhongzhen11 opened this issue Apr 12, 2020 · 0 comments
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Apr 12, 2020

js数据类型:BigInt

为何需要这个数据类型?

Number.MAX_SAFE_INTEGER // 9007199254740991
Number.MAX_SAFE_INTEGER + 2 // 9007199254740992
9007199254740993 // 控制台输出:9007199254740992
2 ** 53 - 1 // 9007199254740991
Number.MIN_SAFE_INTEGER // -9007199254740991

是的,没有看错,我以前也从没意识到这个问题,毕竟这种数我在业务中没有接触过。今天开始研究 BigInt 看它介绍才意识到这个问题。

说到底还是 IEEE 754-2019 64位双精度浮点数的问题(这个又和二进制有关,二进制又是计算机基础,所以像我一样非科班的转行者必须要花时间自己补习下基础知识)。

由于ECMAScript采用的是 64位 双精度浮点数。抛开 IEEE 754-2019 不谈,普通64位数其实就是64个二进制组成的数。有点二进制基础的应该都知道,64位数能表示的无符号数范围是 -264 ~ 264 - 1,但这里是 IEEE 754-2019 64位双精度浮点数,其中只有53位有效位,所以其表示的无符号数范围应该在 -253 ~ 253 - 1

253 - 1 正好就是 Number.MAX_SAFE_INTEGER。不过这里 Number.MIN_SAFE_INTEGER 却是 -253 + 1

由上面可知 Number 能表示的数的安全范围,所以超出这个范围的数,Number 表示会有问题,为了解决这种问题,就引进了新的数据类型 BigInt但是,它只能表示整数!!!

// 没有问题
9007199254740993n // 9007199254740993n
2n ** 53n + 2n // 9007199254740994n
BigInt(Number.MAX_SAFE_INTEGER) + 2n // 9007199254740993n

9007199254740993.5n // Uncaught SyntaxError: Invalid or unexpected token

BigInt 类型

BigInt类型表示 数学整数 值。其值可以是任何大小,并且不限于特定的位宽(没有大小限制)。除非另有说明,它的运算和设计是用来返回精确的数学答案。对于位运算而言,BigInts充当两个二进制字符串的补码,负数被视为将位无限地设置在左边。

BigInt::unit 值为 1n

BigInt::unaryMinus( x ) 一元减

-0n // 0n
-1n // -1n
-(-1n) // 1n
  1. 如果 x0n,返回 0n
  2. 返回表示 x 的负数学数的 BigInt 值

BigInt::bitwiseNOT( x ) 按位非

~0n // -1n
~1n // -2n
~(-1n) // 0n

该抽象运算伴有BigInt类型的参数 x 返回 x 的补码;即 -x - 1

BigInt::exponentiate( base, exponent ) 求幂

1n ** -1n // Uncaught RangeError: Exponent must be positive
0n ** 0n // 1n
2n ** 2n // 4n
  1. 如果 exponent < 0n,抛 RangeError 异常
  2. 如果 base0nexponent 也是 0n,返回 1n
  3. 返回表示 基数幂次方对应的数学值的 BigInt值

BigInt::multiply( x, y ) 乘法

1n * 2n // 2n

BigInt::divide( x, y ) 除

0n / 0n // Uncaught RangeError: Division by zero
1n / 2n // 0n
1n / 3n // 0n
  1. 如果 y0n,抛 RangeError 异常
  2. 定义 quotientx / y 的数学值
  3. 返回表示 quotient 朝0舍入到下一个整数的 BigInt值(应该是舍去小数位,只保留整数位,不是数学上的四舍五入

BigInt::remainder( n, d ) 取余

3n % 2n // 1n
  1. 如果 d0n,抛 RangeError 异常
  2. 如果 n0n,返回 0n
  3. 定义 r 为由数学关系式 r = n - (d × q) 定义的BigInt,其中 q 是正负符合由 n/d 决定的 BigInt,其大小尽可能的大且不超过 nd 的真实数学商的大小
  4. 返回 r

BigInt::add( x, y ) +

0n + 1n // 1n

BigInt::subtract( x, y ) -

0n - 1n // -1n

BigInt::leftShift( x, y ) 左移

1n << -1n // 0n
-1n << -1n // -1n
1n << 1n // 2n
  1. 如果 y < 0n
    1. 返回表示 x ÷ 2-y 的BigInt值,向下舍入到最近的整数,包括负数
  2. 返回表示 x × 2y 的BigInt值

BigInt::signedRightShift( x, y ) 有符号右移

1n >> 1n // 0n
  1. 返回 BigInt::leftShift(x, -y)

BigInt::unsignedRightShift( x, y ) 无符号右移

1n >>> 1n // Uncaught TypeError: BigInts have no unsigned right shift, use >> instead
  1. TypeError 异常

BigInt::lessThan( x, y )

1n < 2n // true
1n < 1n // false

BigInt::equal( x, y )

1n === 1n // true

如果 xy 有相同的 数学整数 值,则返回 true,否则返回 false

BigInt::sameValue( x, y )

  1. 返回 BigInt::equal(x, y)

BigInt::sameValueZero( x, y )

  1. 返回 BigInt::equal(x, y)

BinaryAnd( x, y ) 二进制与

二进制运算

  1. 断言:x 是0或1
  2. 断言:y 是0或1
  3. 如果 x 是 1 且 y 是1,返回1
  4. 否则,返回 0

BinaryOr( x, y ) 二进制或

二进制运算

  1. 断言:x 是0或1
  2. 断言:y 是0或1
  3. 如果 x 是 1 或 y 是1,返回1
  4. 否则,返回 0

BinaryXor( x, y ) 二进制异或

二进制运算

  1. 断言:x 是0或1
  2. 断言:y 是0或1
  3. 如果 x 是 1 且 y 是0,返回1
  4. 如果 x 是 0 且 y 是1,返回1
  5. 否则,返回 0

BigIntBitwiseOp( op, x, y )

  1. 断言:op"&","|"或"^"
  2. 定义 result0n
  3. 定义 shift0
  4. 重复,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1),
    1. 定义 xDigitx 取模 2
    2. 定义 yDigity 取模 2
    3. 如果 op"&",设置 resultresult + 2shift × BinaryAnd(xDigit, yDigit)
    4. 如果 op"|",设置 resultresult + 2shift × BinaryOr(xDigit, yDigit)
    5. 否则,
      1. 断言:op"^"
      2. 设置 resultresult + 2shift × BinaryXor(xDigit, yDigit)
    6. 设置 shiftshift + 1
    7. 设置 x(x - xDigit) / 2
    8. 设置 y(y - yDigit) / 2
  5. 如果 op"&",定义 tmpBinaryAnd(x 取模 2, y 取模 2)
  6. 如果 op"|",定义 tmpBinaryOr(x 取模 2, y 取模 2)
  7. 否则,
    1. 断言:op"^"
    2. 定义 tmpBinaryXor(x 取模 2, y 取模 2)
  8. 如果 tmp ≠ 0
    1. 设置 resultresult - 2shift
    2. 注意:这里扩展了符合
  9. 返回 result

BigInt::bitwiseAND( x, y ) 按位与

  1. 返回 BigIntBitwiseOp("&", x, y)

BigInt::bitwiseXOR( x, y ) 按位异或

  1. 返回 BigIntBitwiseOp("^", x, y)

BigInt::bitwiseOR( x, y ) 按位或

  1. 返回 BigIntBitwiseOp("|", x, y)

BigInt::toString( x )

  1. 如果 x 小于 0,返回字符串 '-'!BigInt::toString( -x ) 的字符串拼接
  2. 返回 x 十进制表示形式数字的码元组成的字符串值
@lizhongzhen11 lizhongzhen11 added js基础 Good for newcomers 重学js 重学js系列 规范+MDN labels Apr 12, 2020
@lizhongzhen11 lizhongzhen11 changed the title 重学js —— js数据类型(五):BigInt 重学js —— js数据类型:BigInt Jun 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN
Projects
None yet
Development

No branches or pull requests

1 participant