11

If you try 9n**9n**9n in Chrome's console, Chrome breaks (it resembles an infinite loop).

  • Does the V8 engine lack the implementation for this case?

I mean, if you try 9**9**9 it will return Infinity, which is kind of nice.

  • Why doesn't V8 return Infinity as well in the former case?
  • And why does it seem to go into an infinite loop?

I tried this in Firefox too, and this problem doesn't exist, because currently there's no BigInt implementation in SpiderMonkey.

Thanks!

Boann
  • 48,794
  • 16
  • 117
  • 146
Tiberiu
  • 418
  • 1
  • 3
  • 12
  • 2
    Just a question, what is 9n**9n? Is n any number? Just for clarification. – lloydaf Nov 28 '18 at 10:50
  • 4
    "A BigInt is created by appending n to the end of an integer literal — 10n — or by calling the function BigInt()." This is from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt – Tiberiu Nov 28 '18 at 10:53
  • I use Edge only for reading epubs on my computer. It's very nice. – Tiberiu Nov 28 '18 at 10:59
  • 1
    seems like chrome can go up to `9n**9n**5n` - but the length of that number is also 56349 characters long.. – Stender Nov 28 '18 at 11:03
  • Yes, it is. I use Edge on my mobile phone over Chrome and Firefox, but for a debugging console I use Firefox. – ms2r Nov 28 '18 at 11:11

3 Answers3

10

As was said already, 9n is the BigInt representation of 9.

The ** (power) operator works from right to left, causing quick escalation of results:

2n**2n**2n === 2n ** 4n === 16n
3n**3n**3n === 3n ** 27n === 7625597484987n
4n**4n**4n === 4n ** 256n === 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096n

On my system this becomes quite laggy from 7n**7n**7n, which takes about 32 seconds to calculate print. The result is 695976 digits, the first 5000 of which are printed in the console.

I haven't tried it any further, but I'd say it is just chewing away on the result. This could well take hours or days to calculate print (or perhaps even an Out Of Memory situation might occur at some point).

Update:

I just tried var x = 7n**7n**7n in the Chrome console, so just assigning it to a variable, and this finished in almost no time. It turns out that converting the bigint to a string is what takes up time; printing x.toString().length takes a similar amount of time as printing x or 7n**7n**7n.

Further experimenting revealed other interesting behaviour, see these results:

// Pure calculation time increases significantly when the exponent grows:
var x = 7n**7n**7n; // ~   1200 ms
var x = 7n**8n**7n; // ~   7000 ms
var x = 7n**7n**8n; // ~  62000 ms
var x = 7n**8n**8n; // ~ 470000 ms

// But it's a different story when the base number is 'simple' in binary terms, e.g. 8n:
var x = 8n**7n**7n; // ~      1 ms
var x = 8n**8n**7n; // ~      1 ms
var x = 8n**7n**8n; // ~      7 ms
var x = 8n**8n**8n; // ~     17 ms

And yes, there is an end to it all:

var x = 32n**16n**8n;

gives:

VM436:1 Uncaught RangeError: Maximum BigInt size exceeded
at <anonymous>:1:28

The upper limit in Chrome appears to be 1 billion bits (1e9 bits), or about 125 MB - Reference: https://github.com/tc39/proposal-bigint/issues/174#issuecomment-437471065

Peter B
  • 22,460
  • 5
  • 32
  • 69
  • I wonder if a powerful system will return Infinity after a while... keen to find out what lies at the end of that hole. – Tiberiu Nov 28 '18 at 11:33
  • Nice man, thanks for your interest! How long did it take for the last calculation (that gives RangeError)? – Tiberiu Nov 28 '18 at 13:48
  • 1
    No time at all, I used a 'simple' base number (32n) for which the engine is optimized and then it flies. It probably sees that a simple bit shift can be used, and for more than 1 billion places to shift it throws. – Peter B Nov 28 '18 at 14:00
  • 2
    V8 developer here. Just to confirm: (1) There is no "Infinity" in BigInts. Every operation either returns a finite BigInt or a RangeError. (2) It is indeed the `.toString` that takes so much time. See https://github.com/tc39/proposal-bigint/issues/166. Try `.toString(16)` if you really need the textual representation of a large BigInt. – jmrk Nov 28 '18 at 19:01
1

Background information:

In JavaScript you can use n suffix for making the number as bigint (simpy big numbers). Big numbers have different ways of computations. Usually they are more "expensive" to compute. It does not use the processors built-in methods for calculations. Instead bigints use soft computations.

Description of the issue:

9n**9n means 9^9 (9*9*9*9*9*9*9*9*9). It is 387420489. Even if you multiply 387420489 by itself it is really big number. But **9n means you want to compute 387420489^9 which is really really very big number. It seems for chrome it takes too long to calculate it or some unknown issue happens.

Basically it must be a bug which needs to be reported. Freezing the browser in weird way is not good user experience.

Adil Aliyev
  • 1,159
  • 2
  • 9
  • 22
  • 2
    `9n**9n**9n` is as same as `9n**(9n**9n)`, not `(9n**9n)**9n` – tsh Nov 28 '18 at 11:00
  • Mathematically saying yes. But the concept does not change. Anyhow it is very big number which is "difficult" to calculate for V8. But the behaviour is weird. Hence it is a bug. – Adil Aliyev Nov 28 '18 at 11:03
  • 1
    Nothing is difficult to calculate `(9n**9n)**9n`. It is not very large indeed. And Chrome answer `196627050475552913618075908526912116283103450944214766927315415537966391196809n` immediately without any problem. – tsh Nov 28 '18 at 11:05
  • Indeed very "small". Just multiply it by itself :p – Adil Aliyev Nov 28 '18 at 11:07
1

The answer as to why 9**9**9 returns Infinity is because it doesn't take very long to overflow the maximum value (around 2^1024). It might even shortcut it with the ** as see if the first number >= 2 and the second number > 1024, then it will be Infinity.

With BigInt, it can represent much, much larger numbers, so that's what it tries to do. It takes a long time to reach "Infinity" with BigInt (EDIT: which would actually be a RangeError exception). Finding 387420489 can be done pretty quick, but 9n**387420489n, where it is multiplying BigInts almost 400 Million times...that takes a while.

A BigInt operation is much slower than a regular int operation. I expect you might get a result (or a RangeError exception) if you wait 20-30 minutes, but could be much longer.

Garr Godfrey
  • 8,257
  • 2
  • 25
  • 23
  • It would be interesting to see if after some time the result is indeed Infinity, but I'm afraid my system isn't capable of that test. It might catch fire. :) – Tiberiu Nov 28 '18 at 11:31
  • 1
    Clarifications: 2^53 is the maximum *integer* value that a double can accurately represent, aka `Number.MAX_SAFE_INTEGER`. The maximum Number value is 2^1024, aka `Number.MAX_VALUE`. This is not V8 specific, it's due to the IEEE 754 spec that most programming languages follow. --- BigInts have no concept of "Infinity", no BigInt operation will ever return Infinity, because the whole point is to be accurate. If the result is too big to be representable, it'll throw a `RangeError`. – jmrk Nov 28 '18 at 19:05
  • @jmrk thanks, I'm going to update answer. I was thinking it would try to preserve integer-ness but that doesn't make sense after some sleep. – Garr Godfrey Nov 28 '18 at 20:59