12

It seems like Array.prototype.sort() is broken with BigInt

This works

const big = [1n, 2n, 3n, 4n];
big.sort();
console.log(big);
// expected output: Array [1n, 2n, 3n, 4n]

But this doesn't :(

const big = [1n, 2n, 3n, 4n];
big.sort((a,b)=>a-b);
console.log(big);
//Error: Cannot convert a BigInt value to a number

or am i doing something wrong?

6
  • Does this answer your question? How to sort an array of integers correctly Commented Dec 24, 2020 at 7:45
  • I think you mis read the question, it seems compare function only expects integer values in return.. Commented Dec 24, 2020 at 7:47
  • I believe BigInt is handled differently from typical numerical values. You may need to use a separate library that makes working with these types of values much easier to properly subtract the two. I haven't worked with BigInt before, but from my limited understanding, that might be the root of the problem. Commented Dec 24, 2020 at 7:48
  • You could do Number(a-b) but not sure if it's the correct way to handle it. It converts the BigInt to number. If the difference is more than Number.MAX_SAFE_INTEGER (2^53 - 1), it will not work Commented Dec 24, 2020 at 7:49
  • 1
    Found this on Mozilla's website, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… (in the 3rd code block). It shows that sorting the way you have it is not supported, and offers a way to do what you are looking for. Commented Dec 24, 2020 at 7:52

3 Answers 3

18

JavaScript sort method requires a function as a parameter that can compare two elements of the array and return either a positive number, or a negative number or zero. Number is the keyword here.

BigInt operations like addition and subtraction returns BigInt type and not a Number type. And that's why the error you are getting.

So, Something like this should do the job

const big = [1n, 2n, 3n, 4n];
big.sort((a ,b) => {
  if(a > b) {
    return 1;
  } else if (a < b){
    return -1;
  } else {
    return 0;
  }
});
console.log(big);

Interestingly, MDN document that I linked to previously, also suggests how to sort an array of BigInts, and it is concise:

Copying the whole section here for posterity:

const mixed = [4n, 6, -12n, 10, 4, 0, 0n]
// ↪  [4n, 6, -12n, 10, 4, 0, 0n]

mixed.sort() // default sorting behavior
// ↪  [ -12n, 0, 0n, 10, 4n, 4, 6 ]

mixed.sort((a, b) => a - b)
// won't work since subtraction will not work with mixed types
// TypeError: can't convert BigInt to number

// sort with an appropriate numeric comparator
mixed.sort((a, b) => (a < b) ? -1 : ((a > b) ? 1 : 0))
// ↪  [ -12n, 0, 0n, 4n, 4, 6, 10 ]
Sign up to request clarification or add additional context in comments.

3 Comments

You also need to return 0 when a === b
I think that should not matter because what difference would it make it the sort method puts one 2n before another 2n or after. Updated the answer, as document says sort should return positive, zero, or negative number.
4

The reason is that a - b in the sort callback function will return a BigInt data type, while sort expects it to return something that is (or can coerce to) a Number data type.

So you can use a > b || -(a < b) as callback expression:

const big = [10n, 9n, 8n, 7n];
big.sort((a, b) => a > b || -(a < b));
console.log(big + ""); // 7,8,9,10

Note that the first version (without sort callback) does not work in general, because then sort will compare the elements as strings. It is clear that this can yield results that are not numerically sorted:

const big = [10n, 9n, 8n, 7n];
big.sort(); // string-based sort
console.log(big + ""); // 10,7,8,9 is wrong

Comments

0

This might appear to be broken at first but its not, the problem is definition of the compare function is always expecting a return value of -1, 0, 1 and it has no reason to expect bigint of -1 0 1 cause they all are in range of normal int.. so this should solve

big.sort((a,b)=>a<b?-1:(a>b?1:0));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.