'Is there a library similar to Math that supports JavaScript BigInt?

I am trying to use some functions of the Math library such as (pow, floor, etc). However, when I try to use them with a Big Int like this...

let x = Math.pow(100n, 100n);

I get

TypeError: Cannot convert a BigInt value to a number

of course I can implement this myself, something like...

const BigMath ={
  pow(num, pow){
    let total;
    for(let i = 0; i < pow; i++){
      if(!total) total = num;
      else total = total * num;
    }
    return total;
  }
} 
let x = BigMath.pow(100n, 100n);

But I don't want to have to go back through and reimplement all of the functions. Especially since it seems like from my implementation it should be able to handle it no problem.

So how do I handle Math.* with a BigInt?



Solution 1:[1]

For pow() you can simply use ** operator:

Math.pow(2, 175)
// 4.789048565205903e+52
2**175
// 4.789048565205903e+52
2n**175n
// 47890485652059026823698344598447161988085597568237568n

floor() like most Math functions is not relevant with integers.

In fact, only 5 Math functions seam to be relevant with integers:

  • Math.abs()
  • Math.max()
  • Math.min()
  • Math.pow()
  • Math.sign()

All the other functions concern real numbers:

  • Trigonometric functions (cos, acos, sin, asin, tan, atan, atan2)
  • Hyperbolic functions (cosh, acosh, sinh, asinh, tanh, atanh)
  • Roots (sqrt, cbrt, hypot)
  • Round (round, ceil, floor, trunc)
  • Logarithm (exp, expm1, log, log10, log1p, log2)
  • Random (random)
  • Bit (clz32, fround, imul)

So, here is the equivalent of Math for BigInt:

const bigMath = {
  abs(x) {
    return x < 0n ? -x : x
  },
  sign(x) {
    if (x === 0n) return 0n
    return x < 0n ? -1n : 1n
  },
  pow(base, exponent) {
    return base ** exponent
  },
  min(value, ...values) {
    for (const v of values)
      if (v < value) value = v
    return value
  },
  max(value, ...values) {
    for (const v of values)
      if (v > value) value = v
    return value
  },
}

Solution 2:[2]

BigInts is a different datatype in its own way you can't have compare not use them as such in an expression

typeof 123;  // 'number'
typeof 123n; // 'bigint'

Numbers can't represent BigInts beyond the safe integer limit that's why it's not allowed to mix operations between BigInts and Numbers (except for comparison operators ===,<,>) as any implicit conversion could lose information

So what you can do is add an implicit casting

Number( Math.pow( Number(100n) , Number(100n) ) ); // 1.0000000000000005e+200

Solution 3:[3]

You can use Basenumber.js which allows BigInt and BigDecimal operations:

Power

let x = Base('100');
let y = Base('100');

let z = x.pow(y);

console.log( z.toString() );
console.log( z.toExponential(1) );
<script src='https://cdn.jsdelivr.net/gh/AlexSp3/Basenumber.js@main/BaseNumber.min.js'></script>

Division

let x = Base('1e+10000');
let y = Base('999999999999999999999999999999999');

let z = x.divide(y);

console.log(z.toString());
console.log(z.toExponential(1));
<script src='https://cdn.jsdelivr.net/gh/AlexSp3/Basenumber.js@main/BaseNumber.min.js'></script>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Vinay
Solution 3 AlexSp3