BigInt and Number coercion by numeric comparison operators

521 Views Asked by At

Will numeric comparison, between a BigInt and a Number, coerce one argument to BigInt, or coerce one argument to Number?

For example, in the following, is 3n coerced to 3, or is 1 coerced to 1n?

console.log(3n > 1) // true

Both operands appear to be converted to a "mathematical value" in 4.k of the IsLessThan abstract operation; a process that is designated ℝ in the specification.

I have no idea what this means, however.

I note that:

console.log(19_999_999_999_999_998 > 19_999_999_999_999_999n) // true

Perhaps the "mathematical value", ℝ, of 19,999,999,999,999,998, is the descriptor for the value 20,000,000,000,000,000, which is the closest possible IEEE754 representation?

I still don't understand if coercion can be said to occur, given that a Number can have a fractional component, and a BigInt cannot.

2

There are 2 best solutions below

4
On BEST ANSWER

Will numeric comparison between a BigInt and a Number coerce one argument to BigInt, or coerce one argument to Number?

Neither. As you read in the spec, their mathematical values are compared.

Consider 2n < 2.4. If both were converted to BigInt, you'd either get an exception ("cannot convert non-integer to BigInt") or you'd get the result false because 2n is not smaller than 2n. But no, we get the result true because "ℝ(2n) < ℝ(2.4)" is "2 < 2.4" which is true.

Consider 9007199254740993n > 9007199254740992. If both were converted to Number values, you'd get the result false because 9007199254740993 is larger than the Number.MAX_SAFE_INTEGER and loses precision, becoming the number value 9007199254740992 which is not larger than 9007199254740992. But no, we get the result true because "ℝ(9007199254740993n) > ℝ(9007199254740992)" is "9007199254740993 > 9007199254740992" which is true.

Perhaps the "mathematical value", ℝ, is the closest possible IEEE754 representation?

No, that's the Number value for x, also denoted as (x), which converts from a mathematical value (the real numbers) or extended mathematical value (the real numbers plus two infinities) to a concrete (IEEE 754 double-precision floating point) Number value. The mathematical values are abstract, and there are many real numbers that can neither be represented accurately as a BigInt or Number.

2
On

Because coercing between Number values and BigInt values can lead to loss of precision, the following are recommended:

Only use a BigInt value when values greater than 2^53 are reasonably expected. Don't coerce between BigInt values and Number values.

The BigInt is converted to a Number (which can lead to loss of precision).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

UPDATE:

For 3n > 1

Bytecode length: 11
Parameter count 6
Register count 2
Frame size 16
OSR nesting level: 0
Bytecode Age: 0
   16 S> 0x28001122e @    0 : 13 00             LdaConstant [0]
         0x280011230 @    2 : c2                Star1 
         0x280011231 @    3 : 0d 01             LdaSmi [1]
   20 E> 0x280011233 @    5 : 6d f9 00          TestGreaterThan r1, [0]
         0x280011236 @    8 : c3                Star0 
         0x280011237 @    9 : 0e                LdaUndefined 
   24 S> 0x280011238 @   10 : a8                Return 
Constant pool (size = 1)
0x2800111c9: [FixedArray] in OldSpace
 - map: 0x0a554d7412c1 <Map>
 - length: 1
           0: 0x0002800111e1 <BigInt 3>
Handler Table (size = 0)
Source Position Table (size = 8)
0x000280011241 <ByteArray[8]>

For TestGreaterThan, it looks like it compares two fixed arrays (BigInt & Int)