146

I found myself in the situation where I wanted to convert a BigInt value to a Number value. Knowing that my value is a safe integer, how can I convert it?

2
  • 4
    Are you referring to the Stage 3 proposal? That would be documented there. Commented Dec 29, 2018 at 15:03
  • Nice @Xufox, thanks for the edit. Commented Dec 29, 2018 at 15:14

4 Answers 4

210

Turns out it's as easy as passing it to the Number constructor:

const myBigInt = BigInt(10);  // `10n` also works
const myNumber = Number(myBigInt);

Of course, you should bear in mind that your BigInt value must be within [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER] for the conversion to work properly, as stated in the question.

2
30

You can use parseInt or Number

const large =  BigInt(309);
const b = parseInt(large);
console.log(b);
const n = Number(large);
console.log(n);

6
  • 8
    For performance reasons, I suggest not using parseInt for this. Yes, yes, according to the specs, both parseInt and Number ought to perform the conversion by converting the BigInt to a string before to a number. Nevertheless, the semantics of parseInt compared to the semantics of Number especially in view of how BigInt(number) yields a BigInt makes it more likely that browser vendors will apply more optimizations to Number(bigValue) than parseInt(bigValue) such that the stringification is internally skipped. Thus, I suggest using Number instead of parseInt for performance.
    – Jack G
    Commented Feb 14, 2020 at 16:59
  • @JackGiffin please see this stackoverflow.com/questions/4090518/… where parseInt can be better in some cases Commented Feb 14, 2020 at 17:12
  • 1
    I am afraid that I do not understand. I agree that parseInt and Number have different behaviors, but, for the purposes of converting a BigInt to a number, I can think of no cases where they would differ. Perhaps you could provide an example of where Number and parseInt differ in conversion of BigInts to numbers to enlighten me. Thank you very much.
    – Jack G
    Commented Feb 15, 2020 at 19:44
  • @JackGiffin You are totally right in this case of BigInts and what I need to show is that parseInt and Number have different behaviors and you can see the example in the link above. Commented Feb 15, 2020 at 20:15
  • 2
    @I_Al-thamary: best practice is to use radix while using parseInt Commented Jan 7, 2022 at 13:30
3

Avoiding Caveats

I know the scope of the original question is knowing you already have a "safe integer", but I wanted to give scope to others that land here how they should try to handle it.

Number.isSafeInteger

One would think you could utilize Number.isSafeInteger, but something trivial like the following snippet will show that utilizing the function on a BigInt will always be false even if the value is within the minimum and maximum bounds of a Number.

console.log(Number.isSafeInteger(BigInt(1)))
// Returns false

An Implementation using Results

This utilizes the TS-Results library to return a success or error response, rather than doing something like throwing.

If you do not want to use the Results library, you could instead return the value and throw otherwise, or handle it however you see appropriate.

import { Err, Ok, Result } from 'ts-results'

export function bigIntToNumber(value: bigint): Result<number, Error> {
  if (validInterger(value)) {
    return Ok(Number(value))
  }

  return Err(new Error(`Value: "${value}" is out of bounds to be a Number`))
}

function validInteger(value: bigint): boolean {
  return value <= Number.MAX_SAFE_INTEGER && value >= Number.MIN_SAFE_INTEGER
}

An Aside on Data Types and Data Ranges

Something interesting to note is that a JS number go up to 9,007,199,254,740,991 (the Number.MAX_SAFE_INTEGER) while your classic 4-byte integer would only be 2,147,483,647, thus a JS Number can hold more, but not as much as an 8-byte integer which goes up to 9,223,372,036,854,775,807.

As noted in comments there can be numbers past Number.MAX_SAFE_INTEGER up to Number.MAX_VALUE that are still technically valid JS Numbers. You can read more here:

1
  • Your last paragraph, as currently phrased, is incorrect. For example, 10_000_000_000_000_000_000 is totally a valid JS number. I know what you mean (2**53 - 1 is between 2**31 - 1 and 2**63 - 1, sure!), but that's not what that paragraph is currently saying. Another way of putting it: Number.MAX_SAFE_INTEGER != Number.MAX_VALUE. You're talking about the former, but JS numbers "go up to" (or "can hold" up to) the latter.
    – jmrk
    Commented Nov 10, 2023 at 14:17
1

Edit: see the discussion in the comments below as to why this answer is not correct. I am leaving the answer up regardless for disambiguation.

You should use either of the static methods:

BigInt.asIntN() - Clamps a BigInt value to a signed integer value, and returns that value. BigInt.asUintN() - Clamps a BigInt value to an unsigned integer value, and returns that value.

as documented here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#static_methods

4
  • 8
    @zr0gravity7 @naveen, I had the chance to test this and these methods do not return numbers, but BigInt values instead. Their names are misleading, as the N suggests Number, when in fact they still return BigInt values. Try running typeof BigInt.asIntN(64, 1n) to see that it reports bigint. So this answer actually does not answer the question. Commented Jan 7, 2022 at 14:57
  • 1
    True that. A confusing name. Was reading the documentation. <3 Commented Jan 7, 2022 at 15:42
  • 6
    The explanation of the name is that "intN" is the generalization of "int32", "int64", "int555" and so on; or put differently: "intN" is short for "N-bit integer". The value of this N is the first parameter to the function. An alternative spec could have provided BigInt.asInt64(x) and BigInt.asInt32(x), but for maximum flexibility the decision was made to have a single BigInt.asIntN(N, x) instead.
    – jmrk
    Commented Jan 12, 2022 at 11:35
  • 4
    as(Ui|I)ntN does not do what you claim nor does this answer OP's question. These functions take a BigInt and return a BigInt modulo 2^N.
    – Chris_F
    Commented Aug 3, 2022 at 7:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.